Salome HOME
Merge branch 'Dev_2.8.0'
authornds <nds@opencascade.com>
Wed, 4 Oct 2017 04:39:24 +0000 (07:39 +0300)
committernds <nds@opencascade.com>
Wed, 4 Oct 2017 04:39:24 +0000 (07:39 +0300)
Conflicts:
src/XGUI/XGUI_DataModel.h
src/XGUI/XGUI_OperationMgr.cpp

100 files changed:
CMakeLists.txt
src/FeaturesAPI/CMakeLists.txt
src/FeaturesAPI/FeaturesAPI.i
src/FeaturesAPI/FeaturesAPI_MultiRotation.cpp [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_MultiRotation.h [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_MultiTranslation.h
src/FeaturesAPI/FeaturesAPI_swig.h
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp
src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_MultiRotation.h [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.h
src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp
src/FeaturesPlugin/Test/Test1942.py
src/FeaturesPlugin/Test/Test2255.py [new file with mode: 0644]
src/FeaturesPlugin/icons/SVG/multirotation.svg [new file with mode: 0644]
src/FeaturesPlugin/icons/multirotation.png [new file with mode: 0644]
src/FeaturesPlugin/multirotation_widget.xml [new file with mode: 0644]
src/FeaturesPlugin/plugin-Features.xml
src/GDMLPlugin/CMakeLists.txt
src/GDMLPlugin/GDMLPlugin_ConeSegment.cpp
src/GDMLPlugin/GDMLPlugin_Ellipsoid.cpp [new file with mode: 0644]
src/GDMLPlugin/GDMLPlugin_Ellipsoid.h [new file with mode: 0644]
src/GDMLPlugin/GDMLPlugin_Plugin.cpp
src/GDMLPlugin/ellipsoid_widget.xml [new file with mode: 0644]
src/GDMLPlugin/icons/ellipsoid.png [new file with mode: 0644]
src/GDMLPlugin/icons/gui_ellipsoid.png [new file with mode: 0644]
src/GDMLPlugin/plugin-GDML.xml
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI_Cone.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Cone.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Cylinder.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Cylinder.h
src/GeomAlgoAPI/GeomAlgoAPI_Ellipsoid.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Ellipsoid.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Rotation.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.h
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h
src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Sphere.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Torus.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Torus.h [new file with mode: 0644]
src/Model/Model_AttributeSelection.cpp
src/Model/Model_BodyBuilder.cpp
src/Model/Model_ResultCompSolid.cpp
src/Model/Model_ResultCompSolid.h
src/Model/Model_SelectionNaming.cpp
src/ModelAPI/ModelAPI_ResultCompSolid.h
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModelHighAPI/ModelHighAPI_Selection.cpp
src/ModelHighAPI/ModelHighAPI_Tools.cpp
src/ModuleBase/ModuleBase_ModelWidget.cpp
src/ModuleBase/ModuleBase_ModelWidget.h
src/ModuleBase/ModuleBase_WidgetEditor.cpp
src/ModuleBase/ModuleBase_WidgetEditor.h
src/PrimitivesAPI/CMakeLists.txt
src/PrimitivesAPI/PrimitivesAPI.i
src/PrimitivesAPI/PrimitivesAPI_Cone.cpp [new file with mode: 0644]
src/PrimitivesAPI/PrimitivesAPI_Cone.h [new file with mode: 0644]
src/PrimitivesAPI/PrimitivesAPI_Cylinder.cpp
src/PrimitivesAPI/PrimitivesAPI_Cylinder.h
src/PrimitivesAPI/PrimitivesAPI_Sphere.cpp [new file with mode: 0644]
src/PrimitivesAPI/PrimitivesAPI_Sphere.h [new file with mode: 0644]
src/PrimitivesAPI/PrimitivesAPI_Torus.cpp [new file with mode: 0644]
src/PrimitivesAPI/PrimitivesAPI_Torus.h [new file with mode: 0644]
src/PrimitivesAPI/PrimitivesAPI_swig.h
src/PrimitivesPlugin/CMakeLists.txt
src/PrimitivesPlugin/PrimitivesPlugin_Cone.cpp [new file with mode: 0644]
src/PrimitivesPlugin/PrimitivesPlugin_Cone.h [new file with mode: 0644]
src/PrimitivesPlugin/PrimitivesPlugin_Cylinder.cpp
src/PrimitivesPlugin/PrimitivesPlugin_Plugin.cpp
src/PrimitivesPlugin/PrimitivesPlugin_Sphere.cpp [new file with mode: 0644]
src/PrimitivesPlugin/PrimitivesPlugin_Sphere.h [new file with mode: 0644]
src/PrimitivesPlugin/PrimitivesPlugin_Torus.cpp [new file with mode: 0644]
src/PrimitivesPlugin/PrimitivesPlugin_Torus.h [new file with mode: 0644]
src/PrimitivesPlugin/cone_widget.xml [new file with mode: 0644]
src/PrimitivesPlugin/icons/SVG/cone.svg [new file with mode: 0644]
src/PrimitivesPlugin/icons/SVG/torus.svg [new file with mode: 0644]
src/PrimitivesPlugin/icons/cone.png [new file with mode: 0644]
src/PrimitivesPlugin/icons/sphere.png [new file with mode: 0644]
src/PrimitivesPlugin/icons/torus.png [new file with mode: 0644]
src/PrimitivesPlugin/plugin-Primitives.xml
src/PrimitivesPlugin/sphere_widget.xml [new file with mode: 0644]
src/PrimitivesPlugin/torus_widget.xml [new file with mode: 0644]
src/PythonAPI/model/features/__init__.py
src/PythonAPI/model/primitives/__init__.py
src/XGUI/XGUI_DataModel.cpp
src/XGUI/XGUI_DataModel.h
src/XGUI/XGUI_MenuMgr.cpp
src/XGUI/XGUI_OperationMgr.cpp
src/XGUI/XGUI_OperationMgr.h
test.API/SHAPER/CMakeLists.txt
test.API/SHAPER/Primitives/TestCone.py [new file with mode: 0644]
test.API/SHAPER/Primitives/TestSphere.py [new file with mode: 0644]
test.API/SHAPER/Primitives/TestTorus.py [new file with mode: 0644]
test.API/SHAPER/Transformations/TestMultiRotation.py [new file with mode: 0644]
test.API/SHAPER/Transformations/TestRotation.py

index 9475e015fe68cab8df6632a56ae29290d4d584e9..0ea92c020143bab617426d0d7c81a4b6b8376fd0 100644 (file)
@@ -27,7 +27,7 @@ IF(WIN32)
   CMAKE_POLICY(SET CMP0020 OLD) # disable automatic linking to qtmain.lib
 ENDIF(WIN32)
 
-SET (SHAPER_Version 2.7.2)
+SET (SHAPER_Version 2.8.0)
 
 SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeCommon" ${CMAKE_MODULE_PATH})
 
index 5ba13f39d8425a5e605594fd0dda5ea64a96dfbd..791859eedd8d904a1846a1f271742ca1c1e91647 100644 (file)
@@ -26,6 +26,7 @@ SET(PROJECT_HEADERS
   FeaturesAPI_Extrusion.h
   FeaturesAPI_ExtrusionBoolean.h
   FeaturesAPI_Intersection.h
+  FeaturesAPI_MultiRotation.h
   FeaturesAPI_MultiTranslation.h
   FeaturesAPI_Partition.h
   FeaturesAPI_Pipe.h
@@ -46,6 +47,7 @@ SET(PROJECT_SOURCES
   FeaturesAPI_Extrusion.cpp
   FeaturesAPI_ExtrusionBoolean.cpp
   FeaturesAPI_Intersection.cpp
+  FeaturesAPI_MultiRotation.cpp
   FeaturesAPI_MultiTranslation.cpp
   FeaturesAPI_Partition.cpp
   FeaturesAPI_Pipe.cpp
index c15889876d89fc5ac71415a4885cb3242ef40ae2..e77373949f43a83a4012c468cb321f6b38173e7e 100644 (file)
@@ -45,6 +45,7 @@
 %shared_ptr(FeaturesAPI_ExtrusionCut)
 %shared_ptr(FeaturesAPI_ExtrusionFuse)
 %shared_ptr(FeaturesAPI_Intersection)
+%shared_ptr(FeaturesAPI_MultiRotation)
 %shared_ptr(FeaturesAPI_MultiTranslation)
 %shared_ptr(FeaturesAPI_Partition)
 %shared_ptr(FeaturesAPI_Pipe)
@@ -66,6 +67,7 @@
 %include "FeaturesAPI_Extrusion.h"
 %include "FeaturesAPI_ExtrusionBoolean.h"
 %include "FeaturesAPI_Intersection.h"
+%include "FeaturesAPI_MultiRotation.h"
 %include "FeaturesAPI_MultiTranslation.h"
 %include "FeaturesAPI_Partition.h"
 %include "FeaturesAPI_Pipe.h"
diff --git a/src/FeaturesAPI/FeaturesAPI_MultiRotation.cpp b/src/FeaturesAPI/FeaturesAPI_MultiRotation.cpp
new file mode 100644 (file)
index 0000000..9d23177
--- /dev/null
@@ -0,0 +1,144 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:        FeaturesAPI_MultiRotation.cpp
+// Created:     04 Apr 2017
+// Author:      Clarisse Genrault (CEA)
+
+#include <FeaturesAPI_MultiRotation.h>
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+//==================================================================================================
+FeaturesAPI_MultiRotation::FeaturesAPI_MultiRotation(
+  const std::shared_ptr<ModelAPI_Feature>& theFeature)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+
+//==================================================================================================
+FeaturesAPI_MultiRotation::FeaturesAPI_MultiRotation(
+  const std::shared_ptr<ModelAPI_Feature>& theFeature,
+  const std::list<ModelHighAPI_Selection>& theMainObjects,
+  const ModelHighAPI_Selection& theAxis,
+  const ModelHighAPI_Integer& theNumber)
+: ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    fillAttribute(theMainObjects, mainObjects());
+    fillAttribute(theAxis, axisAngular());
+    fillAttribute("",useStepAngular());
+    setNumberAngular(theNumber);
+  }
+}
+
+//==================================================================================================
+FeaturesAPI_MultiRotation::FeaturesAPI_MultiRotation(
+  const std::shared_ptr<ModelAPI_Feature>& theFeature,
+  const std::list<ModelHighAPI_Selection>& theMainObjects,
+  const ModelHighAPI_Selection& theAxis,
+  const ModelHighAPI_Double& theStep,
+  const ModelHighAPI_Integer& theNumber)
+: ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    fillAttribute(theMainObjects, mainObjects());
+    fillAttribute(theAxis, axisAngular());
+    fillAttribute(FeaturesPlugin_MultiRotation::USE_ANGULAR_STEP_ID(),useStepAngular());
+    fillAttribute(theStep, stepAngular());
+    setNumberAngular(theNumber);
+  }
+}
+
+//==================================================================================================
+FeaturesAPI_MultiRotation::~FeaturesAPI_MultiRotation()
+{
+}
+
+//==================================================================================================
+void FeaturesAPI_MultiRotation::setMainObjects(
+  const std::list<ModelHighAPI_Selection>& theMainObjects)
+{
+  fillAttribute(theMainObjects, mainObjects());
+
+  execute();
+}
+
+//==================================================================================================
+void FeaturesAPI_MultiRotation::setAxisAngular(const ModelHighAPI_Selection& theAxis)
+{
+  fillAttribute(theAxis, axisAngular());
+
+  execute();
+}
+
+//==================================================================================================
+void FeaturesAPI_MultiRotation::setStepAngular(const ModelHighAPI_Double& theStep)
+{
+  fillAttribute(theStep, stepAngular());
+
+  execute();
+}
+
+//==================================================================================================
+void FeaturesAPI_MultiRotation::setNumberAngular(const ModelHighAPI_Integer& theNumber)
+{
+  fillAttribute(theNumber, nbAngular());
+
+  execute();
+}
+
+//==================================================================================================
+void FeaturesAPI_MultiRotation::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionListPtr anAttrObjects =
+    aBase->selectionList(FeaturesPlugin_MultiRotation::OBJECTS_LIST_ID());
+  theDumper << aBase << " = model.addMultiRotation(" << aDocName << ", " << anAttrObjects;
+
+  AttributeSelectionPtr anAttrAxis =
+    aBase->selection(FeaturesPlugin_MultiRotation::AXIS_ANGULAR_ID());
+  theDumper << ", " << anAttrAxis;
+
+  if (aBase->string(FeaturesPlugin_MultiRotation::USE_ANGULAR_STEP_ID())->isInitialized()
+      && !aBase->string(FeaturesPlugin_MultiRotation::USE_ANGULAR_STEP_ID())->value().empty()) {
+    AttributeDoublePtr anAttrStepAngular =
+      aBase->real(FeaturesPlugin_MultiRotation::STEP_ANGULAR_ID());
+      theDumper << ", " << anAttrStepAngular;
+  }
+
+  AttributeIntegerPtr anAttrNumberAngular =
+    aBase->integer(FeaturesPlugin_MultiRotation::NB_COPIES_ANGULAR_ID());
+  theDumper << ", " << anAttrNumberAngular;
+
+  theDumper << ")" << std::endl;
+}
+
+//==================================================================================================
+MultiRotationPtr addMultiRotation(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                  const std::list<ModelHighAPI_Selection>& theMainObjects,
+                                  const ModelHighAPI_Selection& theAxis,
+                                  const ModelHighAPI_Integer& theNumber)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    thePart->addFeature(FeaturesAPI_MultiRotation::ID());
+  return MultiRotationPtr(new FeaturesAPI_MultiRotation(aFeature, theMainObjects,
+                                                        theAxis, theNumber));
+}
+
+//==================================================================================================
+MultiRotationPtr addMultiRotation(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                  const std::list<ModelHighAPI_Selection>& theMainObjects,
+                                  const ModelHighAPI_Selection& theAxis,
+                                  const ModelHighAPI_Double& theStep,
+                                  const ModelHighAPI_Integer& theNumber)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    thePart->addFeature(FeaturesAPI_MultiRotation::ID());
+  return MultiRotationPtr(new FeaturesAPI_MultiRotation(aFeature, theMainObjects,
+                                                        theAxis, theStep, theNumber));
+}
\ No newline at end of file
diff --git a/src/FeaturesAPI/FeaturesAPI_MultiRotation.h b/src/FeaturesAPI/FeaturesAPI_MultiRotation.h
new file mode 100644 (file)
index 0000000..d1ae1c7
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:        FeaturesAPI_MultiRotation.h
+// Created:     04 Apr 2017
+// Author:      Clarisse Genrault (CEA)
+
+#ifndef FEATURESAPI_MULTIROTATION_H_
+#define FEATURESAPI_MULTIROTATION_H_
+
+#include "FeaturesAPI.h"
+
+#include <FeaturesPlugin_MultiRotation.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Double;
+class ModelHighAPI_Dumper;
+class ModelHighAPI_Integer;
+class ModelHighAPI_Selection;
+
+/// \class FeaturesAPI_MultiRotation
+/// \ingroup CPPHighAPI
+/// \brief Interface for Translation feature.
+class FeaturesAPI_MultiRotation: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_MultiRotation(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  FEATURESAPI_EXPORT
+  FeaturesAPI_MultiRotation(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                            const std::list<ModelHighAPI_Selection>& theMainObjects,
+                            const ModelHighAPI_Selection& theAxis,
+                            const ModelHighAPI_Integer& theNumber);
+
+  /// Constructor with values.
+  FEATURESAPI_EXPORT
+  FeaturesAPI_MultiRotation(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                            const std::list<ModelHighAPI_Selection>& theMainObjects,
+                            const ModelHighAPI_Selection& theAxis,
+                            const ModelHighAPI_Double& theStep,
+                            const ModelHighAPI_Integer& theNumber);
+
+  /// Destructor.
+  FEATURESAPI_EXPORT
+  virtual ~FeaturesAPI_MultiRotation();
+
+  INTERFACE_5(FeaturesPlugin_MultiRotation::ID(),
+              mainObjects, FeaturesPlugin_MultiRotation::OBJECTS_LIST_ID(),
+              ModelAPI_AttributeSelectionList, /** Main objects */,
+              axisAngular, FeaturesPlugin_MultiRotation::AXIS_ANGULAR_ID(),
+              ModelAPI_AttributeSelection, /** Angular direction */,
+              useStepAngular, FeaturesPlugin_MultiRotation::USE_ANGULAR_STEP_ID(),
+              ModelAPI_AttributeString, /** Use step angular */,
+              stepAngular, FeaturesPlugin_MultiRotation::STEP_ANGULAR_ID(),
+              ModelAPI_AttributeDouble, /** Step angular */,
+              nbAngular, FeaturesPlugin_MultiRotation::NB_COPIES_ANGULAR_ID(),
+              ModelAPI_AttributeInteger, /** Number of copies for angular */
+             )
+
+  /// Set main objects.
+  FEATURESAPI_EXPORT
+  void setMainObjects(const std::list<ModelHighAPI_Selection>& theMainObjects);
+
+  /// Modify CreationMethod, axis_angular attribute of the feature.
+  FEATURESAPI_EXPORT
+  void setAxisAngular(const ModelHighAPI_Selection& theAxis);
+
+  /// Modify CreationMethod, step_angular attribute of the feature.
+  FEATURESAPI_EXPORT
+  void setStepAngular(const ModelHighAPI_Double& theStep);
+
+  /// Modify CreationMethod, nb_angular attribute of the feature.
+  FEATURESAPI_EXPORT
+  void setNumberAngular(const ModelHighAPI_Integer& theNumber);
+
+  /// Dump wrapped feature
+  FEATURESAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Multirotation object.
+typedef std::shared_ptr<FeaturesAPI_MultiRotation> MultiRotationPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create MultiRotation feature.
+FEATURESAPI_EXPORT
+MultiRotationPtr addMultiRotation(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                  const std::list<ModelHighAPI_Selection>& theMainObjects,
+                                  const ModelHighAPI_Selection& theAxis,
+                                  const ModelHighAPI_Integer& theNumber);
+
+/// \ingroup CPPHighAPI
+/// \brief Create MultiRotation feature.
+FEATURESAPI_EXPORT
+MultiRotationPtr addMultiRotation(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                  const std::list<ModelHighAPI_Selection>& theMainObjects,
+                                  const ModelHighAPI_Selection& theAxis,
+                                  const ModelHighAPI_Double& theStep,
+                                  const ModelHighAPI_Integer& theNumber);
+
+#endif // FEATURESAPI_MULTIROTATION_H_
index 479ad686d1dc0e2210527d2f3bdd4768c2a1f2e4..70b76ff60e67c9e5a3148283ab52c8ea4bbced96 100644 (file)
@@ -112,7 +112,7 @@ public:
   virtual void dump(ModelHighAPI_Dumper& theDumper) const;
 };
 
-/// Pointer on Translation object.
+/// Pointer on MultiTranslation object.
 typedef std::shared_ptr<FeaturesAPI_MultiTranslation> MultiTranslationPtr;
 
 /// \ingroup CPPHighAPI
index 4ecbdd964b9ec4b465af5f517a5216232021d67f..9a6637c03bffd8aa6229af5ea5d4c5fd5523fccf 100644 (file)
@@ -28,6 +28,7 @@
   #include "FeaturesAPI_Extrusion.h"
   #include "FeaturesAPI_ExtrusionBoolean.h"
   #include "FeaturesAPI_Intersection.h"
+  #include "FeaturesAPI_MultiRotation.h"
   #include "FeaturesAPI_MultiTranslation.h"
   #include "FeaturesAPI_Partition.h"
   #include "FeaturesAPI_Pipe.h"
index 94ec4f78c0078de437949bf82ea57bb709326c10..53b6ad50eb1e8e3c229e3e54efc54835d4695d69 100644 (file)
@@ -50,6 +50,7 @@ SET(PROJECT_HEADERS
     FeaturesPlugin_Symmetry.h
     FeaturesPlugin_Scale.h
     FeaturesPlugin_MultiTranslation.h
+    FeaturesPlugin_MultiRotation.h
 )
 
 SET(PROJECT_SOURCES
@@ -80,6 +81,7 @@ SET(PROJECT_SOURCES
     FeaturesPlugin_Symmetry.cpp
     FeaturesPlugin_Scale.cpp
     FeaturesPlugin_MultiTranslation.cpp
+    FeaturesPlugin_MultiRotation.cpp
 )
 
 SET(XML_RESOURCES
@@ -103,6 +105,7 @@ SET(XML_RESOURCES
   symmetry_widget.xml
   scale_widget.xml
   multitranslation_widget.xml
+  multirotation_widget.xml
 )
 
 SET(TEXT_RESOURCES
@@ -181,4 +184,5 @@ ADD_UNIT_TESTS(TestExtrusion.py
                Test2246.py
                Test2248.py
                Test2251.py
+               Test2255.py
 )
index 6f200a6c7329c8c4e6518ec89be640e2729ff48d..f54449b36ed98d0e6939561bcfea1eebfab2ef8f 100644 (file)
@@ -78,20 +78,27 @@ void FeaturesPlugin_CompositeBoolean::executeCompositeBoolean()
     int aTag = 1;
 
     ResultBodyPtr aResultBody = myFeature->document()->createBody(myFeature->data(), aResultIndex);
-    aResultBody->storeModified(*aBoolObjIt, (*aBoolMSIt)->shape(), aTag);
 
-    aTag += 5000;
-
-    // Store generation history.
-    ListOfShape::const_iterator aGenBaseIt = aGenBaseShapes.cbegin();
-    ListOfMakeShape::const_iterator aGenMSIt = aGenMakeShapes.cbegin();
-    for(; aGenBaseIt != aGenBaseShapes.cend() && aGenMSIt != aGenMakeShapes.cend();
-        ++aGenBaseIt, ++aGenMSIt) {
-      storeGenerationHistory(aResultBody, *aGenBaseIt, *aGenMSIt, aTag);
+    if((*aBoolObjIt)->isEqual((*aBoolMSIt)->shape())) {
+      aResultBody->store((*aBoolMSIt)->shape(), false);
     }
+    else
+    {
+      aResultBody->storeModified(*aBoolObjIt, (*aBoolMSIt)->shape(), aTag);
+
+      aTag += 5000;
+
+      // Store generation history.
+      ListOfShape::const_iterator aGenBaseIt = aGenBaseShapes.cbegin();
+      ListOfMakeShape::const_iterator aGenMSIt = aGenMakeShapes.cbegin();
+      for(; aGenBaseIt != aGenBaseShapes.cend() && aGenMSIt != aGenMakeShapes.cend();
+          ++aGenBaseIt, ++aGenMSIt) {
+        storeGenerationHistory(aResultBody, *aGenBaseIt, *aGenMSIt, aTag);
+      }
 
-    int aModTag = aTag;
-    storeModificationHistory(aResultBody, *aBoolObjIt, aTools, *aBoolMSIt, aModTag);
+      int aModTag = aTag;
+      storeModificationHistory(aResultBody, *aBoolObjIt, aTools, *aBoolMSIt, aModTag);
+    }
 
     myFeature->setResult(aResultBody, aResultIndex++);
   }
diff --git a/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp b/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp
new file mode 100644 (file)
index 0000000..3bd55a6
--- /dev/null
@@ -0,0 +1,481 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D
+
+// File:        FeaturesPlugin_MultiRotation.cpp
+// Created:     30 Jan 2017
+// Author:      Clarisse Genrault (CEA)
+
+#include <FeaturesPlugin_MultiRotation.h>
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_Translation.h>
+
+#include <GeomAPI_ShapeExplorer.h>
+
+#include <GeomAPI_Ax1.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Lin.h>
+#include <GeomAPI_Trsf.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultPart.h>
+
+#include <math.h>
+#include <iostream>
+
+//=================================================================================================
+FeaturesPlugin_MultiRotation::FeaturesPlugin_MultiRotation()
+{
+}
+
+//=================================================================================================
+void FeaturesPlugin_MultiRotation::initAttributes()
+{
+  AttributeSelectionListPtr aSelection =
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
+    FeaturesPlugin_MultiRotation::OBJECTS_LIST_ID(),
+    ModelAPI_AttributeSelectionList::typeId()));
+
+  data()->addAttribute(FeaturesPlugin_MultiRotation::AXIS_ANGULAR_ID(),
+                       ModelAPI_AttributeSelection::typeId());
+  data()->addAttribute(FeaturesPlugin_MultiRotation::USE_ANGULAR_STEP_ID(),
+                       ModelAPI_AttributeString::typeId());
+  data()->addAttribute(FeaturesPlugin_MultiRotation::STEP_ANGULAR_ID(),
+                       ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(FeaturesPlugin_MultiRotation::NB_COPIES_ANGULAR_ID(),
+                       ModelAPI_AttributeInteger::typeId());
+
+  /*data()->addAttribute(FeaturesPlugin_MultiRotation::USE_RADIAL_DIR_ID(),
+                       ModelAPI_AttributeString::typeId());
+  data()->addAttribute(FeaturesPlugin_MultiRotation::STEP_RADIAL_ID(),
+                       ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(FeaturesPlugin_MultiRotation::NB_COPIES_RADIAL_ID(),
+                       ModelAPI_AttributeInteger::typeId());*/
+}
+
+//=================================================================================================
+void FeaturesPlugin_MultiRotation::execute()
+{
+  /*std::string useRadialDir = string(FeaturesPlugin_MultiRotation::USE_RADIAL_DIR_ID())->value();
+  if (useRadialDir.empty()) {
+    performRotation1D();
+  } else {
+    performRotation2D();
+  }*/
+  performRotation1D();
+}
+
+//=================================================================================================
+void FeaturesPlugin_MultiRotation::performRotation1D()
+{
+  // Getting objects.
+  ListOfShape anObjects;
+  std::list<ResultPtr> aContextes;
+  AttributeSelectionListPtr anObjectsSelList =
+    selectionList(FeaturesPlugin_MultiRotation::OBJECTS_LIST_ID());
+  if (anObjectsSelList->size() == 0) {
+    return;
+  }
+  for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
+    std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
+      anObjectsSelList->value(anObjectsIndex);
+    std::shared_ptr<GeomAPI_Shape> 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<GeomAPI_Ax1> anAxis;
+  std::shared_ptr<GeomAPI_Edge> anEdge;
+  std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
+    selection(FeaturesPlugin_MultiRotation::AXIS_ANGULAR_ID());
+  if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->value()));
+  } else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
+             anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->context()->shape()));
+  }
+  if(anEdge) {
+    anAxis = std::shared_ptr<GeomAPI_Ax1>(new GeomAPI_Ax1(anEdge->line()->location(),
+                                                          anEdge->line()->direction()));
+  }
+
+  // Getting number of copies.
+  int nbCopies =
+    integer(FeaturesPlugin_MultiRotation::NB_COPIES_ANGULAR_ID())->value();
+
+  if (nbCopies <=0) {
+    std::string aFeatureError = "Multirotation builder ";
+    aFeatureError+=":: the number of copies for the angular direction is null or negative.";
+    setError(aFeatureError);
+    return;
+  }
+
+  // Getting angle
+  double anAngle;
+  std::string useAngularStep =
+    string(FeaturesPlugin_MultiRotation::USE_ANGULAR_STEP_ID())->value();
+  if (!useAngularStep.empty()) {
+    anAngle = real(FeaturesPlugin_MultiRotation::STEP_ANGULAR_ID())->value();
+  } else {
+    anAngle = 360./nbCopies;
+  }
+
+  // Moving each object.
+  int aResultIndex = 0;
+  std::list<ResultPtr>::iterator aContext = aContextes.begin();
+  for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
+        anObjectsIt++, aContext++) {
+    std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
+    bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group();
+
+    // Setting result.
+    if (isPart) {
+      ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
+      std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
+      for (int i=0; i<nbCopies; i++) {
+        aTrsf->setRotation(anAxis, i*anAngle);
+        ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
+        aResultPart->setTrsf(*aContext, aTrsf);
+        setResult(aResultPart, aResultIndex);
+        aResultIndex++;
+      }
+    } else {
+      ListOfShape aListOfShape;
+      std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > aListOfRotationAlgo;
+
+      for (int i=0; i<nbCopies; i++) {
+        std::shared_ptr<GeomAlgoAPI_Rotation> aRotationnAlgo(
+          new GeomAlgoAPI_Rotation(aBaseShape, anAxis, i*anAngle));
+
+        if (!aRotationnAlgo->check()) {
+          setError(aRotationnAlgo->getError());
+          break;
+        }
+
+        aRotationnAlgo->build();
+
+        // Checking that the algorithm worked properly.
+        if (!aRotationnAlgo->isDone()) {
+          static const std::string aFeatureError = "Error : Multitranslation algorithm failed.";
+          setError(aFeatureError);
+          break;
+        }
+        if (aRotationnAlgo->shape()->isNull()) {
+          static const std::string aShapeError = "Error : Resulting shape is null.";
+          setError(aShapeError);
+          break;
+        }
+        if (!aRotationnAlgo->isValid()) {
+          static const std::string aFeatureError = "Error : Resulting shape in not valid.";
+          setError(aFeatureError);
+          break;
+        }
+        aListOfShape.push_back(aRotationnAlgo->shape());
+        aListOfRotationAlgo.push_back(aRotationnAlgo);
+      }
+      std::shared_ptr<GeomAPI_Shape> aCompound =
+        GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
+      ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
+      aResultBody->storeModified(aBaseShape, aCompound);
+      loadNamingDS(aListOfRotationAlgo, aResultBody, aBaseShape);
+
+      setResult(aResultBody, aResultIndex);
+    }
+    aResultIndex++;
+  }
+
+  // Remove the rest results if there were produced in the previous pass.
+  removeResults(aResultIndex);
+}
+
+//=================================================================================================
+void FeaturesPlugin_MultiRotation::performRotation2D()
+{
+  // Getting objects.
+  ListOfShape anObjects;
+  std::list<ResultPtr> aContextes;
+  AttributeSelectionListPtr anObjectsSelList =
+    selectionList(FeaturesPlugin_MultiRotation::OBJECTS_LIST_ID());
+  if (anObjectsSelList->size() == 0) {
+    return;
+  }
+  for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
+    std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
+      anObjectsSelList->value(anObjectsIndex);
+    std::shared_ptr<GeomAPI_Shape> 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<GeomAPI_Ax1> anAxis;
+  std::shared_ptr<GeomAPI_Edge> anEdge;
+  std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
+    selection(FeaturesPlugin_MultiRotation::AXIS_ANGULAR_ID());
+  if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->value()));
+  } else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
+             anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->context()->shape()));
+  }
+  if(anEdge) {
+    anAxis = std::shared_ptr<GeomAPI_Ax1>(new GeomAPI_Ax1(anEdge->line()->location(),
+                                                          anEdge->line()->direction()));
+  }
+
+  // Getting number of copies int he angular direction.
+  int nbAngular =
+    integer(FeaturesPlugin_MultiRotation::NB_COPIES_ANGULAR_ID())->value();
+
+  if (nbAngular <=0) {
+    std::string aFeatureError = "Multirotation builder ";
+    aFeatureError+=":: the number of copies for the angular direction is null or negative.";
+    setError(aFeatureError);
+    return;
+  }
+
+  // Getting number of copies int he radial direction.
+  int nbRadial =
+    integer(FeaturesPlugin_MultiRotation::NB_COPIES_RADIAL_ID())->value();
+
+  if (nbRadial <=0) {
+    std::string aFeatureError = "Multirotation builder ";
+    aFeatureError+=":: the number of copies for the radial direction is null or negative.";
+    setError(aFeatureError);
+    return;
+  }
+
+  // Getting angle
+  double anAngle;
+  std::string useAngularStep =
+    string(FeaturesPlugin_MultiRotation::USE_ANGULAR_STEP_ID())->value();
+  if (!useAngularStep.empty()) {
+    anAngle = real(FeaturesPlugin_MultiRotation::STEP_ANGULAR_ID())->value();
+  } else {
+    anAngle = 360./nbAngular;
+  }
+
+  // Getting step
+  double aStep = real(FeaturesPlugin_MultiRotation::STEP_RADIAL_ID())->value();
+
+  // Moving each object.
+  int aResultIndex = 0;
+  std::list<ResultPtr>::iterator aContext = aContextes.begin();
+  for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
+        anObjectsIt++, aContext++) {
+    std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
+    bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group();
+
+    std::shared_ptr<GeomAPI_Dir> aDir =
+      GeomAlgoAPI_ShapeTools::buildDirFromAxisAndShape(aBaseShape, anAxis);
+    double x = aDir->x();
+    double y = aDir->y();
+    double z = aDir->z();
+    double norm = sqrt(x*x+y*y+z*z);
+
+    // Setting result.
+    if (isPart) {
+      /*ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
+      std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
+      for (int j=0; j<aSecondNbCopies; j++) {
+        for (int i=0; i<aFirstNbCopies; i++) {
+          double dx = i*aFirstStep*x1/norm1+j*aSecondStep*x2/norm2;
+          double dy = i*aFirstStep*y1/norm1+j*aSecondStep*y2/norm2;
+          double dz = i*aFirstStep*z1/norm1+j*aSecondStep*z2/norm2;
+          aTrsf->setTranslation(dx, dy, dz);
+          ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
+          aResultPart->setTrsf(*aContext, aTrsf);
+          setResult(aResultPart, aResultIndex);
+          aResultIndex++;
+        }
+      }*/
+    } else {
+      ListOfShape aListOfShape;
+      std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
+      std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > aListOfRotationAlgo;
+      for (int j=0; j<nbRadial; j++) {
+        // Translation
+        double dx = j*aStep*x/norm;
+        double dy = j*aStep*y/norm;
+        double dz = j*aStep*z/norm;
+        std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
+          new GeomAlgoAPI_Translation(aBaseShape, dx, dy, dz));
+
+        if (!aTranslationAlgo->check()) {
+          setError(aTranslationAlgo->getError());
+          break;
+        }
+
+        aTranslationAlgo->build();
+
+        // Checking that the algorithm worked properly.
+        if (!aTranslationAlgo->isDone()) {
+          static const std::string aFeatureError = "Error : Multirotation algorithm failed.";
+          setError(aFeatureError);
+          break;
+        }
+        if (aTranslationAlgo->shape()->isNull()) {
+          static const std::string aShapeError = "Error : Resulting shape is null.";
+          setError(aShapeError);
+          break;
+        }
+        if (!aTranslationAlgo->isValid()) {
+          static const std::string aFeatureError = "Error : Resulting shape in not valid.";
+          setError(aFeatureError);
+          break;
+        }
+        aListOfShape.push_back(aTranslationAlgo->shape());
+        aListOfTranslationAlgo.push_back(aTranslationAlgo);
+        for (int i=1; i<nbAngular; i++) {
+          std::shared_ptr<GeomAlgoAPI_Rotation> aRotationnAlgo(
+            new GeomAlgoAPI_Rotation(aTranslationAlgo->shape(), anAxis, i*anAngle));
+          if (!aRotationnAlgo->check()) {
+            setError(aTranslationAlgo->getError());
+            break;
+          }
+          aRotationnAlgo->build();// Checking that the algorithm worked properly.
+          if (!aRotationnAlgo->isDone()) {
+            static const std::string aFeatureError = "Error : Multirotation algorithm failed.";
+            setError(aFeatureError);
+            break;
+          }
+          if (aRotationnAlgo->shape()->isNull()) {
+            static const std::string aShapeError = "Error : Resulting shape is null.";
+            setError(aShapeError);
+            break;
+          }
+          if (!aRotationnAlgo->isValid()) {
+            static const std::string aFeatureError = "Error : Resulting shape in not valid.";
+            setError(aFeatureError);
+            break;
+          }
+          aListOfShape.push_back(aRotationnAlgo->shape());
+          aListOfRotationAlgo.push_back(aRotationnAlgo);
+        }
+      }
+      std::shared_ptr<GeomAPI_Shape> aCompound =
+        GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
+      ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
+      aResultBody->storeModified(aBaseShape, aCompound);
+
+      loadNamingDS2(aListOfTranslationAlgo, aResultBody, aBaseShape);
+      loadNamingDS3(aListOfRotationAlgo, aResultBody, aBaseShape, nbRadial);
+      setResult(aResultBody, aResultIndex);
+    }
+    aResultIndex++;
+  }
+
+  // Remove the rest results if there were produced in the previous pass.
+  removeResults(aResultIndex);
+}
+
+//=================================================================================================
+void FeaturesPlugin_MultiRotation::loadNamingDS2(
+    std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
+    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+    std::shared_ptr<GeomAPI_Shape> theBaseShape)
+{
+  int aTag = 1;
+  int anIndex = 1;
+  std::string aRotatedName;
+
+  for (std::list<std::shared_ptr<GeomAlgoAPI_Translation> >::const_iterator anIt =
+    theListOfTranslationAlgo.begin(); anIt != theListOfTranslationAlgo.cend(); ++anIt) {
+    std::cout << "LOAD" << std::endl;
+    std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes = (*anIt)->mapOfSubShapes();
+
+    // naming of faces
+    aRotatedName = "Rotated_Face_" + std::to_string((long long) anIndex);
+    theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::FACE,
+                                               aTag++, aRotatedName, *aSubShapes.get(),
+                                               false, true);
+
+    // naming of edges
+    aRotatedName = "Rotated_Edge_" + std::to_string((long long) anIndex);
+    theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::EDGE,
+                                               aTag++, aRotatedName, *aSubShapes.get(),
+                                               false, true);
+
+    // naming of vertex
+    aRotatedName = "Rotated_Vertex_" + std::to_string((long long) anIndex);
+    theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::VERTEX,
+                                               aTag++, aRotatedName, *aSubShapes.get(),
+                                               false, true);
+
+    ++anIndex;
+  }
+}
+
+//=================================================================================================
+void FeaturesPlugin_MultiRotation::loadNamingDS3(
+    std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
+    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+    std::shared_ptr<GeomAPI_Shape> theBaseShape, int nb)
+{
+  int aTag = 6*nb+1;
+  int anIndex = nb+1;
+  std::string aRotatedName;
+
+  for (std::list<std::shared_ptr<GeomAlgoAPI_Rotation> >::const_iterator anIt =
+    theListOfRotationAlgo.begin(); anIt != theListOfRotationAlgo.cend(); ++anIt) {
+
+    // naming of faces
+    int numFace = 1;
+    GeomAPI_ShapeExplorer anExp((*anIt)->shape(), GeomAPI_Shape::FACE);
+    for(; anExp.more(); anExp.next()) {
+       aRotatedName = "Rotated_Face_" + std::to_string((long long) anIndex);
+       aRotatedName = aRotatedName + "_" + std::to_string((long long) numFace);
+       theResultBody->generated(anExp.current(), aRotatedName, aTag++);
+       ++numFace;
+    }
+    ++anIndex;
+  }
+}
+
+//=================================================================================================
+void FeaturesPlugin_MultiRotation::loadNamingDS(
+    std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
+    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+    std::shared_ptr<GeomAPI_Shape> theBaseShape)
+{
+  int aTag = 1;
+  int anIndex = 1;
+  std::string aRotatedName;
+
+  for (std::list<std::shared_ptr<GeomAlgoAPI_Rotation> >::const_iterator anIt =
+    theListOfRotationAlgo.begin(); anIt != theListOfRotationAlgo.cend(); ++anIt) {
+    std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes = (*anIt)->mapOfSubShapes();
+
+    // naming of faces
+    aRotatedName = "Rotated_Face_" + std::to_string((long long) anIndex);
+    theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::FACE,
+                                               aTag++, aRotatedName, *aSubShapes.get(),
+                                               false, true);
+
+    // naming of edges
+    aRotatedName = "Rotated_Edge_" + std::to_string((long long) anIndex);
+    theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::EDGE,
+                                               aTag++, aRotatedName, *aSubShapes.get(),
+                                               false, true);
+
+    // naming of vertex
+    aRotatedName = "Rotated_Vertex_" + std::to_string((long long) anIndex);
+    theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::VERTEX,
+                                               aTag++, aRotatedName, *aSubShapes.get(),
+                                               false, true);
+    ++anIndex;
+  }
+}
diff --git a/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.h b/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.h
new file mode 100644 (file)
index 0000000..32746de
--- /dev/null
@@ -0,0 +1,125 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D
+
+// File:        FeaturesPlugin_MultiRotation.h
+// Created:     30 Jan 2017
+// Author:      Clarisse Genrault (CEA)
+
+#ifndef FEATURESPLUGIN_MULTIROTATION_H_
+#define FEATURESPLUGIN_MULTIROTATION_H_
+
+#include <FeaturesPlugin.h>
+
+#include <GeomAlgoAPI_Rotation.h>
+#include <GeomAlgoAPI_Translation.h>
+
+#include <ModelAPI_Feature.h>
+
+/** \class FeaturesPlugin_MultiRotation
+ *  \ingroup Plugins
+ *  \brief Feature that rotaes object around an axis an number of times.
+ *         The 2D version also makes translated copies of the object and performs the rotation
+ *         on these as well.
+ */
+class FeaturesPlugin_MultiRotation : public ModelAPI_Feature
+{
+  public:
+  /// Multi-rotation kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_MULTIROTATION_ID("MultiRotation");
+    return MY_MULTIROTATION_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 the angular direction.
+  inline static const std::string& AXIS_ANGULAR_ID()
+  {
+    static const std::string MY_AXIS_ANGULAR_ID("axis_angular");
+    return MY_AXIS_ANGULAR_ID;
+  }
+
+  /// Attribute name for use angular step.
+  inline static const std::string& USE_ANGULAR_STEP_ID()
+  {
+    static const std::string MY_USE_ANGULAR_STEP_ID("use_step_angular");
+    return MY_USE_ANGULAR_STEP_ID;
+  }
+
+  /// Attribute name of step for the angular.
+  inline static const std::string& STEP_ANGULAR_ID()
+  {
+    static const std::string MY_STEP_ANGULAR_ID("step_angular");
+    return MY_STEP_ANGULAR_ID;
+  }
+
+  /// Attribute name of number of copies for angular.
+  inline static const std::string& NB_COPIES_ANGULAR_ID()
+  {
+    static const std::string MY_NB_COPIES_ANGULAR_ID("nb_angular");
+    return MY_NB_COPIES_ANGULAR_ID;
+  }
+
+  /// Attribute name for use radial dir.
+  inline static const std::string& USE_RADIAL_DIR_ID()
+  {
+    static const std::string MY_USE_RADIAL_DIR_ID("use_radial_dir");
+    return MY_USE_RADIAL_DIR_ID;
+  }
+
+  /// Attribute name of radial step.
+  inline static const std::string& STEP_RADIAL_ID()
+  {
+    static const std::string MY_STEP_RADIAL_ID("step_radial");
+    return MY_STEP_RADIAL_ID;
+  }
+
+  /// Attribute name of number of copies for radial.
+  inline static const std::string& NB_COPIES_RADIAL_ID()
+  {
+    static const std::string MY_NB_COPIES_RADIAL_ID("nb_radial");
+    return MY_NB_COPIES_RADIAL_ID;
+  }
+
+  /// \return the kind of a feature.
+  FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = FeaturesPlugin_MultiRotation::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_MultiRotation();
+
+private:
+  /// Perform the multi rotation in one direction.
+  void performRotation1D();
+
+  /// Perform the multi totation in two directions.
+  void performRotation2D();
+
+  void loadNamingDS2(std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
+                    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+                    std::shared_ptr<GeomAPI_Shape> theBaseShape);
+
+  void loadNamingDS3(std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
+                    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+                    std::shared_ptr<GeomAPI_Shape> theBaseShape, int nb);
+
+  void loadNamingDS(std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
+                    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+                    std::shared_ptr<GeomAPI_Shape> theBaseShape);
+};
+
+#endif // FEATURESPLUGIN_MULTIROTATION_H_
\ No newline at end of file
index 388f0ce48d787ed51ef547f733af8a04c5d29c73..480d89931f9a5a5d1c577bc1b94370ac11ab51d4 100644 (file)
@@ -35,7 +35,7 @@
 class FeaturesPlugin_MultiTranslation : public ModelAPI_Feature
 {
   public:
-  /// Translation kind.
+  /// Multi-translation kind.
   inline static const std::string& ID()
   {
     static const std::string MY_MULTITRANSLATION_ID("MultiTranslation");
index 21a258e9c6856b3bafe595e9b858f4437fbd50b2..954a0fb3c6786f30618271f2d7055b038dd8eea9 100644 (file)
@@ -25,6 +25,7 @@
 #include <FeaturesPlugin_ExtrusionCut.h>
 #include <FeaturesPlugin_ExtrusionFuse.h>
 #include <FeaturesPlugin_Intersection.h>
+#include <FeaturesPlugin_MultiRotation.h>
 #include <FeaturesPlugin_MultiTranslation.h>
 #include <FeaturesPlugin_Partition.h>
 #include <FeaturesPlugin_Pipe.h>
@@ -128,6 +129,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID)
     return FeaturePtr(new FeaturesPlugin_Scale);
   } else if (theFeatureID == FeaturesPlugin_MultiTranslation::ID()) {
     return FeaturePtr(new FeaturesPlugin_MultiTranslation);
+  } else if (theFeatureID == FeaturesPlugin_MultiRotation::ID()) {
+    return FeaturePtr(new FeaturesPlugin_MultiRotation);
   }
 
   // feature of such kind is not found
index 9d2cb804fe8af656eb11618db96513e0a2d132a7..93272c18752581d0a4de093c5d518a8128ddfdc8 100644 (file)
@@ -182,7 +182,7 @@ Plane_5 = model.addPlane(Part_1_doc, model.selection("EDGE", "PartSet/Axis_4"),
 Face_1 = model.addFace(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchArc_2_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_5"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_6"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_7"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_8"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2")])
 Intersection_1 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Recover_1_1")], [model.selection("FACE", "Face_1_1")])
 Group_1 = model.addGroup(Part_1_doc, [model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_2_1"), model.selection("VERTEX", "Intersection_1_1/Generated_Vertex_2"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_6_1"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_4_1"), model.selection("VERTEX", "Intersection_1_1/Generated_Vertex_3"), model.selection("VERTEX", "Intersection_1_1/Generated_Vertex_1"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_1_1"), model.selection("VERTEX", "Intersection_1_1/Generated_Vertex_4"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_3_1"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_7_1"), model.selection("VERTEX", "Intersection_1_1/Modified_Vertex_5_1")])
-Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Intersection_1_1_7"), model.selection("EDGE", "Intersection_1_1_6"), model.selection("EDGE", "Intersection_1_1_3"), model.selection("EDGE", "Intersection_1_1_11"), model.selection("EDGE", "Recover_1_1/Shape33"), model.selection("EDGE", "Recover_1_1/Shape18"), model.selection("EDGE", "Recover_1_1/Shape32"), model.selection("EDGE", "Intersection_1_1_2"), model.selection("EDGE", "Intersection_1_1_10"), model.selection("EDGE", "Intersection_1_1_9"), model.selection("EDGE", "Intersection_1_1_8")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "Intersection_1_1_7"), model.selection("EDGE", "Intersection_1_1_6"), model.selection("EDGE", "Intersection_1_1_3"), model.selection("EDGE", "Intersection_1_1_11"), model.selection("EDGE", "Intersection_1_1_5"), model.selection("EDGE", "Intersection_1_1_1"), model.selection("EDGE", "Intersection_1_1_4"), model.selection("EDGE", "Intersection_1_1_2"), model.selection("EDGE", "Intersection_1_1_10"), model.selection("EDGE", "Intersection_1_1_9"), model.selection("EDGE", "Intersection_1_1_8")])
 model.end()
 
 aGroupFeature = Group_1.feature()
diff --git a/src/FeaturesPlugin/Test/Test2255.py b/src/FeaturesPlugin/Test/Test2255.py
new file mode 100644 (file)
index 0000000..92193a3
--- /dev/null
@@ -0,0 +1,78 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(40.12837458064153, 0, 0, 0)
+SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "PartSet/Origin"))
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchPoint_1.result())
+SketchLine_2 = Sketch_1.addLine(0, 0, 0, 44.52500071883479)
+SketchLine_3 = Sketch_1.addLine(0, 44.52500071883479, 40.12837458064153, 44.52500071883479)
+SketchLine_4 = Sketch_1.addLine(40.12837458064153, 44.52500071883479, 40.12837458064153, 0)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 24.97092001270093)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchCircle_1.center())
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_4"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_1")])
+Wire_2 = model.addWire(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchCircle_1_2")])
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Wire_1_1")])
+Face_2 = model.addFace(Part_1_doc, [model.selection("WIRE", "Wire_2_1")])
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("FACE", "Face_2_1")], model.selection(), 50, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "PartSet/YOZ"))
+SketchLine_5 = Sketch_2.addLine(49.62901186301215, 25.3130971701971, 39.15939470736273, 25.3130971701971)
+SketchLine_6 = Sketch_2.addLine(39.15939470736273, 25.3130971701971, 39.15939470736273, 38.96586914453801)
+SketchLine_7 = Sketch_2.addLine(39.15939470736273, 38.96586914453801, 49.62901186301215, 38.96586914453801)
+SketchLine_8 = Sketch_2.addLine(49.62901186301215, 38.96586914453801, 49.62901186301215, 25.3130971701971)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result())
+SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result())
+model.do()
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_5r-SketchLine_6r-SketchLine_7r-SketchLine_8r")], model.selection(), 50, 50, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_2")])
+model.do()
+model.end()
+
+from GeomAPI import  GeomAPI_Shape
+
+model.testNbResults(ExtrusionCut_1, 2)
+model.testNbSubResults(ExtrusionCut_1, [0, 0])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.SOLID, [1, 1])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.FACE, [10, 3])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.EDGE, [48, 6])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.VERTEX, [96, 12])
+model.testResultsVolumes(ExtrusionCut_1, [86396.175406624068273231387138367, 97946.509572227776516228914260864])
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/icons/SVG/multirotation.svg b/src/FeaturesPlugin/icons/SVG/multirotation.svg
new file mode 100644 (file)
index 0000000..b84eaa9
--- /dev/null
@@ -0,0 +1,495 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="16"
+   height="16"
+   id="svg11250"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   viewBox="0 0 16 16"
+   sodipodi:docname="multi_rotation.svg"
+   inkscape:export-filename="/export/home/ldigallo/DOC_ALYOTECH/icones/Transformations/multi_rotation.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs11252">
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4903"
+       is_visible="true" />
+    <marker
+       inkscape:stockid="TriangleOutS"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker8735"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path8737"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="scale(0.2,0.2)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutS"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutS"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path5715"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="scale(0.2,0.2)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect13212"
+       is_visible="true" />
+    <marker
+       inkscape:stockid="EmptyTriangleOutS"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="EmptyTriangleOutS"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path5733"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#ffffff;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(0.2,0,0,0.2,-0.6,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path5712"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="scale(0.4,0.4)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Send"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Send"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path5582"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect12156"
+       is_visible="true" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 16 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="32 : 16 : 1"
+       inkscape:persp3d-origin="16 : 10.666667 : 1"
+       id="perspective12136" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect12134"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="skeletal"
+       id="path-effect12130"
+       is_visible="true"
+       pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
+       copytype="single_stretched"
+       prop_scale="1"
+       scale_y_rel="false"
+       spacing="0"
+       normal_offset="0"
+       tang_offset="0"
+       prop_units="false"
+       vertical_pattern="false"
+       fuse_tolerance="0" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect12128"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="skeletal"
+       id="path-effect12124"
+       is_visible="true"
+       pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
+       copytype="single_stretched"
+       prop_scale="1"
+       scale_y_rel="false"
+       spacing="0"
+       normal_offset="0"
+       tang_offset="0"
+       prop_units="false"
+       vertical_pattern="false"
+       fuse_tolerance="0" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect12122"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="skeletal"
+       id="path-effect12118"
+       is_visible="true"
+       pattern="m -0.04465162,5 c 0,-2.76 2.24000002,-5 5.00000002,-5 2.76,0 5,2.24 5,5 0,2.76 -2.24,5 -5,5 -2.76,0 -5.00000002,-2.24 -5.00000002,-5 z"
+       copytype="single_stretched"
+       prop_scale="1"
+       scale_y_rel="false"
+       spacing="0"
+       normal_offset="0"
+       tang_offset="0"
+       prop_units="false"
+       vertical_pattern="false"
+       fuse_tolerance="0" />
+    <marker
+       inkscape:stockid="TriangleOutS"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker18553-4"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path18555-7"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="scale(0.2,0.2)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutS"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker18553-3"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path18555-3"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="scale(0.2,0.2)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutS"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker18553-5"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path18555-73"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="scale(0.2,0.2)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutS"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker8735-6"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path8737-0"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="scale(0.2,0.2)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutS"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker8735-3"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path8737-1"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="scale(0.2,0.2)" />
+    </marker>
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4481"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4481-6"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4481-6-3"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4481-1"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4481-1-4"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4359"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4734"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4359-3"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4734-3"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4359-85"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4734-0"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4359-8"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4734-4"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4812"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4481-5"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4481-9-0"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4481-9"
+       is_visible="true" />
+    <filter
+       inkscape:label="Pixellize"
+       inkscape:menu="Pixel tools"
+       inkscape:menu-tooltip="Reduce or remove antialiasing around shapes"
+       style="color-interpolation-filters:sRGB"
+       id="filter5039-5">
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1000 -500 "
+         id="feColorMatrix5041-7" />
+    </filter>
+    <filter
+       inkscape:label="Pixellize"
+       inkscape:menu="Pixel tools"
+       inkscape:menu-tooltip="Reduce or remove antialiasing around shapes"
+       style="color-interpolation-filters:sRGB"
+       id="filter5039-5-6">
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1000 -500 "
+         id="feColorMatrix5041-7-2" />
+    </filter>
+    <filter
+       inkscape:label="Pixellize"
+       inkscape:menu="Pixel tools"
+       inkscape:menu-tooltip="Reduce or remove antialiasing around shapes"
+       style="color-interpolation-filters:sRGB"
+       id="filter5039-5-6-1">
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1000 -500 "
+         id="feColorMatrix5041-7-2-9" />
+    </filter>
+    <filter
+       inkscape:label="Pixellize"
+       inkscape:menu="Pixel tools"
+       inkscape:menu-tooltip="Reduce or remove antialiasing around shapes"
+       style="color-interpolation-filters:sRGB"
+       id="filter5039-5-6-1-4">
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1000 -500 "
+         id="feColorMatrix5041-7-2-9-3" />
+    </filter>
+    <filter
+       inkscape:label="Pixellize"
+       inkscape:menu="Pixel tools"
+       inkscape:menu-tooltip="Reduce or remove antialiasing around shapes"
+       style="color-interpolation-filters:sRGB"
+       id="filter5039-5-6-1-4-6">
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1000 -500 "
+         id="feColorMatrix5041-7-2-9-3-7" />
+    </filter>
+    <filter
+       inkscape:label="Pixellize"
+       inkscape:menu="Pixel tools"
+       inkscape:menu-tooltip="Reduce or remove antialiasing around shapes"
+       style="color-interpolation-filters:sRGB"
+       id="filter5039-5-6-1-4-6-2">
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1000 -500 "
+         id="feColorMatrix5041-7-2-9-3-7-6" />
+    </filter>
+    <filter
+       inkscape:label="Pixellize"
+       inkscape:menu="Pixel tools"
+       inkscape:menu-tooltip="Reduce or remove antialiasing around shapes"
+       style="color-interpolation-filters:sRGB"
+       id="filter5039-5-6-1-4-6-2-3">
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1000 -500 "
+         id="feColorMatrix5041-7-2-9-3-7-6-9" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="31.672165"
+     inkscape:cx="2.7791679"
+     inkscape:cy="6.2438977"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:window-width="1920"
+     inkscape:window-height="1006"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="1"
+     inkscape:snap-center="false"
+     inkscape:snap-object-midpoints="true"
+     inkscape:snap-others="true"
+     inkscape:snap-nodes="true"
+     inkscape:snap-grids="false"
+     inkscape:object-paths="false"
+     inkscape:snap-intersection-paths="true"
+     inkscape:snap-page="false"
+     showguides="false"
+     inkscape:snap-global="true"
+     inkscape:showpageshadow="false"
+     inkscape:object-nodes="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid11798" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata11255">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     transform="translate(0,-16)">
+    <g
+       transform="matrix(0.61508511,0,0,0.77777773,0.02030893,10.560744)"
+       id="g4929"
+       style="stroke:none;stroke-opacity:1">
+      <path
+         sodipodi:nodetypes="ccccccc"
+         style="fill:#b7d9ea;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m -0.04504951,16.04505 0,-8.0000005 4.00000001,0 0,4.0000005 4,0 0,4 z"
+         id="path4836"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="ccccccccccc"
+         style="fill:#1b4955;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 0.95495049,7.0450495 -1,1 4.00000001,0 0,4.0000005 4,0 0,4 1,-1 0,-4 -4,0 0,-4.0000005 z"
+         id="path4838"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       transform="matrix(0.50384823,0.35279833,-0.44611498,0.63711822,12.416596,13.249382)"
+       id="g4929-3"
+       style="stroke:none;stroke-opacity:1">
+      <path
+         sodipodi:nodetypes="ccccccc"
+         style="fill:#b7d9ea;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m -0.04504951,16.04505 0,-8.0000005 4.00000001,0 0,4.0000005 4,0 0,4 z"
+         id="path4836-4"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="ccccccccccc"
+         style="fill:#1b4955;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 0.95495049,7.0450495 -1,1 4.00000001,0 0,4.0000005 4,0 0,4 1,-1 0,-4 -4,0 0,-4.0000005 z"
+         id="path4838-7"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       transform="matrix(0.2103715,0.57799095,-0.730872,0.26601565,20.064311,22.847031)"
+       id="g4929-3-7"
+       style="stroke:none;stroke-opacity:1">
+      <path
+         sodipodi:nodetypes="ccccccc"
+         style="fill:#b7d9ea;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m -0.04504951,16.04505 0,-8.0000005 4.00000001,0 0,4.0000005 4,0 0,4 z"
+         id="path4836-4-4"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="ccccccccccc"
+         style="fill:#1b4955;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 0.95495049,7.0450495 -1,1 4.00000001,0 0,4.0000005 4,0 0,4 1,-1 0,-4 -4,0 0,-4.0000005 z"
+         id="path4838-7-8"
+         inkscape:connector-curvature="0" />
+    </g>
+    <path
+       style="fill:#fecc02;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.69999999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 0.51277295,27.461033 1.700539,26.273267 3.0808095,27.653538 4.4610798,26.273267 5.6488459,27.461033 4.2685755,28.841304 5.6488459,30.221574 4.4610798,31.40934 3.0808095,30.02907 1.700539,31.40934 0.51277295,30.221574 1.8930434,28.841304 0.51277295,27.461033"
+       id="path4453"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/src/FeaturesPlugin/icons/multirotation.png b/src/FeaturesPlugin/icons/multirotation.png
new file mode 100644 (file)
index 0000000..fb82a1e
Binary files /dev/null and b/src/FeaturesPlugin/icons/multirotation.png differ
diff --git a/src/FeaturesPlugin/multirotation_widget.xml b/src/FeaturesPlugin/multirotation_widget.xml
new file mode 100644 (file)
index 0000000..8396f48
--- /dev/null
@@ -0,0 +1,53 @@
+<!-- Copyright (C) 2014-201x CEA/DEN, EDF R&D -->
+
+<source>
+  <multi_selector id="main_objects"
+                  label="Main objects"
+                  icon=""
+                  tooltip="Select objects"
+                  type_choice="objects"
+                  concealment="true">
+    <validator id="FeaturesPlugin_ValidatorTransform"/>
+  </multi_selector>
+  <groupbox title="Angular direction">
+    <shape_selector id="axis_angular"
+                    icon="icons/Features/axis.png"
+                    label="Axis"
+                    tooltip="Select an edge for the angular direction"
+                    shape_types="edge"
+                    default="">
+      <validator id="GeomValidators_ShapeType" parameters="line"/>
+    </shape_selector>
+    <optionalbox id="use_step_angular" title="Angular step">
+      <doublevalue id="step_angular"
+                   label="Angular step"
+                   step="1.0"
+                   default="0"
+                   tooltip="Step for the angular direction">
+      </doublevalue>
+    </optionalbox>
+    <integervalue id="nb_angular"
+                  label="Nb copies"
+                  step="1"
+                  default="2"
+                  icon=""
+                  tooltip="Number of copies for the first direction">
+    </integervalue>
+  </groupbox>
+  <!--<optionalbox id="use_radial_dir" title="Radial direction">
+    <doublevalue id="step_radial"
+                 label="Step"
+                 step="1.0"
+                 default="0"
+                 icon="icons/Features/dimension_v.png"
+                 tooltip="Step for the radial direction">
+    </doublevalue>
+    <integervalue id="nb_radial"
+                  label="Nb copies"
+                  step="1"
+                  default="2"
+                  icon=""
+                  tooltip="Number of copies for the radial direction">
+    </integervalue>
+  </optionalbox>-->
+</source>
\ No newline at end of file
index 8791a0d01ba68081674c26eaa09b8cdbaa95e5d6..298723427364fc02046e55c5d8f173c59e17625d 100644 (file)
@@ -98,6 +98,9 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
       <feature id="MultiTranslation" title="MultiTranslation" tooltip="Perform multi-translation objects" icon="icons/Features/multitranslation.png">
         <source path="multitranslation_widget.xml"/>
       </feature>
+      <feature id="MultiRotation" title="MultiRotation" tooltip="Perform multi-rotation objects" icon="icons/Features/multirotation.png">
+        <source path="multirotation_widget.xml"/>
+      </feature>
     </group>
   </workbench>
 </plugin>
index 3723e22208b12bed3420a0c2440111ec6a459c8f..ce4ae6a26c5f14c204b8c66271a8079b673f2a2f 100644 (file)
@@ -27,16 +27,19 @@ SET(PROJECT_HEADERS
     GDMLPlugin.h
     GDMLPlugin_Plugin.h
     GDMLPlugin_ConeSegment.h
+    GDMLPlugin_Ellipsoid.h
 )
 
 SET(PROJECT_SOURCES
     GDMLPlugin_Plugin.cpp
     GDMLPlugin_ConeSegment.cpp
+    GDMLPlugin_Ellipsoid.cpp
 )
 
 SET(XML_RESOURCES
   plugin-GDML.xml
   conesegment_widget.xml
+  ellipsoid_widget.xml
 )
 
 INCLUDE_DIRECTORIES(
index fc371beda5a01fee685af9b01f593ee070cae5e3..2429edd78744ceb42dfd34179252e312340cc992 100644 (file)
@@ -23,7 +23,6 @@
 #include <ModelAPI_Data.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_AttributeString.h>
 
 //=================================================================================================
 GDMLPlugin_ConeSegment::GDMLPlugin_ConeSegment() // Nothing to do during instantiation
diff --git a/src/GDMLPlugin/GDMLPlugin_Ellipsoid.cpp b/src/GDMLPlugin/GDMLPlugin_Ellipsoid.cpp
new file mode 100644 (file)
index 0000000..1ab4ce0
--- /dev/null
@@ -0,0 +1,120 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <GDMLPlugin_Ellipsoid.h>
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeString.h>
+
+//=================================================================================================
+GDMLPlugin_Ellipsoid::GDMLPlugin_Ellipsoid() // Nothing to do during instantiation
+{
+}
+
+//=================================================================================================
+void GDMLPlugin_Ellipsoid::initAttributes()
+{
+  data()->addAttribute(GDMLPlugin_Ellipsoid::AX_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(GDMLPlugin_Ellipsoid::BY_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(GDMLPlugin_Ellipsoid::CZ_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(GDMLPlugin_Ellipsoid::USE_ZCUT1_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(GDMLPlugin_Ellipsoid::ZCUT1_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(GDMLPlugin_Ellipsoid::USE_ZCUT2_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(GDMLPlugin_Ellipsoid::ZCUT2_ID(), ModelAPI_AttributeDouble::typeId());
+}
+
+//=================================================================================================
+void GDMLPlugin_Ellipsoid::execute()
+{
+  std::shared_ptr<GeomAlgoAPI_Ellipsoid> anEllipsoidAlgo;
+
+  double aAx = real(AX_ID())->value();
+  double aBy = real(BY_ID())->value();
+  double aCz = real(CZ_ID())->value();
+
+  std::string useZCut1 = string(USE_ZCUT1_ID())->value();
+  std::string useZCut2 = string(USE_ZCUT2_ID())->value();
+
+  double aZCut1 = 0.;
+  if (useZCut1.empty()) {
+    aZCut1 = aCz /2.;
+  } else {
+    aZCut1 = real(ZCUT1_ID())->value();
+  }
+  double aZCut2 = 0.;
+  if (useZCut2.empty()) {
+    aZCut2 = aCz /2.;
+  } else {
+    aZCut2 = real(ZCUT2_ID())->value();
+  }
+
+  anEllipsoidAlgo = std::shared_ptr<GeomAlgoAPI_Ellipsoid>(
+    new GeomAlgoAPI_Ellipsoid(aAx, aBy, aCz, aZCut1, aZCut2));
+
+  // Check with that the arguments for anEllipsoidAlgo are correct
+  if (!anEllipsoidAlgo->check()) {
+    setError(anEllipsoidAlgo->getError(), false);
+    return;
+  }
+
+  anEllipsoidAlgo->build();
+
+  // Check if the creation of the ellipsoid is correct
+  if (!anEllipsoidAlgo->isDone()) {
+    setError(anEllipsoidAlgo->getError(), false);
+    return;
+  }
+
+  // Check if the created ellipsoid is valid
+  if (!anEllipsoidAlgo->checkValid("Ellipsoid builder")) {
+    setError(anEllipsoidAlgo->getError(), false);
+    return;
+  }
+
+  int aResultIndex = 0;
+  ResultBodyPtr aResultEllipsoid = document()->createBody(data(), aResultIndex);
+  loadNamingDS(anEllipsoidAlgo, aResultEllipsoid);
+  setResult(aResultEllipsoid, aResultIndex);
+
+}
+
+//=================================================================================================
+void GDMLPlugin_Ellipsoid::loadNamingDS(std::shared_ptr<GeomAlgoAPI_Ellipsoid> theEllipsoidAlgo,
+                                        std::shared_ptr<ModelAPI_ResultBody> theResultEllipsoid)
+{
+  // Load the result
+  theResultEllipsoid->store(theEllipsoidAlgo->shape());
+
+  // Prepare the naming
+  theEllipsoidAlgo->prepareNamingFaces();
+
+  // Insert to faces
+  int num = 1;
+  std::map< std::string, std::shared_ptr<GeomAPI_Shape> > listOfFaces =
+    theEllipsoidAlgo->getCreatedFaces();
+  for (std::map< std::string, std::shared_ptr<GeomAPI_Shape> >::iterator
+    it=listOfFaces.begin(); it!=listOfFaces.end(); ++it) {
+    std::shared_ptr<GeomAPI_Shape> aFace = (*it).second;
+    theResultEllipsoid->generated(aFace, (*it).first, num++);
+  }
+}
+
diff --git a/src/GDMLPlugin/GDMLPlugin_Ellipsoid.h b/src/GDMLPlugin/GDMLPlugin_Ellipsoid.h
new file mode 100644 (file)
index 0000000..649afcf
--- /dev/null
@@ -0,0 +1,110 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GDMLPLUGIN_ELLIPSOID_H_
+#define GDMLPLUGIN_ELLIPSOID_H_
+
+#include <GDMLPlugin.h>
+#include <ModelAPI_Feature.h>
+#include <GeomAlgoAPI_Ellipsoid.h>
+
+class GeomAPI_Shape;
+class ModelAPI_ResultBody;
+
+/**\class GDMLPlugin_Ellipsoid
+ * \ingroup Plugins
+ * \brief Feature for creation of a GDML Ellipsoid solid.
+ */
+class GDMLPlugin_Ellipsoid : public ModelAPI_Feature
+{
+ public:
+  /// Cone segment kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_CONESEGMENT_ID("Ellipsoid");
+    return MY_CONESEGMENT_ID;
+  }
+  /// attribute name of the inner radius at base of cone
+  inline static const std::string& AX_ID()
+  {
+    static const std::string MY_AX_ID("ax");
+    return MY_AX_ID;
+  }
+  /// attribute name of the outer radius at base of cone
+  inline static const std::string& BY_ID()
+  {
+    static const std::string MY_BY_ID("by");
+    return MY_BY_ID;
+  }
+  /// attribute name of the inner radius at top of cone
+  inline static const std::string& CZ_ID()
+  {
+    static const std::string MY_CZ_ID("cz");
+    return MY_CZ_ID;
+  }
+  /// attribute name of the outer radius at top of cone
+  inline static const std::string& ZCUT1_ID()
+  {
+    static const std::string MY_ZCUT1_ID("zcut1");
+    return MY_ZCUT1_ID;
+  }
+  /// attribute name of the outer radius at top of cone
+  inline static const std::string& USE_ZCUT1_ID()
+  {
+    static const std::string MY_USE_ZCUT1_ID("use_zcut1");
+    return MY_USE_ZCUT1_ID;
+  }
+  /// attribute name of the outer radius at top of cone
+  inline static const std::string& USE_ZCUT2_ID()
+  {
+    static const std::string MY_USE_ZCUT2_ID("use_zcut2");
+    return MY_USE_ZCUT2_ID;
+  }
+  /// attribute name of the outer radius at top of cone
+  inline static const std::string& ZCUT2_ID()
+  {
+    static const std::string MY_ZCUT2_ID("zcut2");
+    return MY_ZCUT2_ID;
+  }
+
+  /// Returns the kind of a feature
+  GDMLPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = GDMLPlugin_Ellipsoid::ID();
+    return MY_KIND;
+  }
+
+  /// Creates a new part document if needed
+  GDMLPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  GDMLPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Use plugin manager for features creation
+  GDMLPlugin_Ellipsoid();
+
+ private:
+  /// Load Naming data structure of the feature to the document
+  void loadNamingDS(std::shared_ptr<GeomAlgoAPI_Ellipsoid> theEllipsoidAlgo,
+                    std::shared_ptr<ModelAPI_ResultBody> theResultEllipsoid);
+
+};
+
+#endif // GDMLPLUGIN_ELLIPSOID_H_
index 28ff7cea4aff80556a0cdac9893bfb1614e151fd..168ae380e05c44db301fc8b368feb11831593518 100644 (file)
@@ -23,6 +23,7 @@
 #include <GDMLPlugin_Plugin.h>
 
 #include <GDMLPlugin_ConeSegment.h>
+#include <GDMLPlugin_Ellipsoid.h>
 
 // the only created instance of this plugin
 static GDMLPlugin_Plugin* MY_GDML_INSTANCE = new GDMLPlugin_Plugin();
@@ -37,7 +38,10 @@ FeaturePtr GDMLPlugin_Plugin::createFeature(std::string theFeatureID)
 {
   if (theFeatureID == GDMLPlugin_ConeSegment::ID()) {
     return FeaturePtr(new GDMLPlugin_ConeSegment);
+  } else if (theFeatureID == GDMLPlugin_Ellipsoid::ID()) {
+    return FeaturePtr(new GDMLPlugin_Ellipsoid);
   }
+
   // feature of such kind is not found
   return FeaturePtr();
 }
diff --git a/src/GDMLPlugin/ellipsoid_widget.xml b/src/GDMLPlugin/ellipsoid_widget.xml
new file mode 100644 (file)
index 0000000..62da54f
--- /dev/null
@@ -0,0 +1,60 @@
+<!--
+Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See http:##www.salome-platform.org/ or
+email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+  <groupbox title="Dimensions">
+    <doublevalue id="ax"
+                 label="ax"
+                 step="1.0"
+                 default="10.0"
+                 tooltip="Enter the x semi axis length">
+    </doublevalue>
+    <doublevalue id="by"
+                 label="by"
+                 step="1.0"
+                 default="20.0"
+                 tooltip="Enter the y semi axis length">
+    </doublevalue>
+    <doublevalue id="cz"
+                 label="cz"
+                 step="1.0"
+                 default="40.0"
+                 tooltip="Enter the z semi axis length">
+    </doublevalue>   
+  </groupbox>
+  <groupbox title="Cuts">
+    <optionalbox id="use_zcut1" title="">
+      <doublevalue id="zcut1" 
+                   label="zcut1" 
+                   tooltip="Enter the lower zcut" 
+                   default="5."
+                   step="1.0"/>
+    </optionalbox>
+    <optionalbox id="use_zcut2" title="">
+      <doublevalue id="zcut2" 
+                   label="zcut2" 
+                   tooltip="Enter the upper zcut" 
+                   default="5."
+                   step="1.0"/>
+    </optionalbox>
+  </groupbox>
+  <label title="" icon="icons/GDML/gui_ellipsoid.png"/>
+</source>
diff --git a/src/GDMLPlugin/icons/ellipsoid.png b/src/GDMLPlugin/icons/ellipsoid.png
new file mode 100644 (file)
index 0000000..4af212b
Binary files /dev/null and b/src/GDMLPlugin/icons/ellipsoid.png differ
diff --git a/src/GDMLPlugin/icons/gui_ellipsoid.png b/src/GDMLPlugin/icons/gui_ellipsoid.png
new file mode 100644 (file)
index 0000000..fb66e33
Binary files /dev/null and b/src/GDMLPlugin/icons/gui_ellipsoid.png differ
index a2f04881f9bdba4cc47b8357953fb5cd77185d6a..9d8cbdf3d0b72a18776f1a88424517612e58cc96 100644 (file)
@@ -22,9 +22,12 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
 <plugin>
   <workbench id="GDML" document="Part">
     <group id="GDML">
-      <feature id="ConeSegment" title="Cone Segment" tooltip="Create a Cone Segment" icon="icons/GDML/cone_segment.png">
+      <feature id="ConeSegment" title="Cone segment" tooltip="Create a GDML Cone Segment" icon="icons/GDML/cone_segment.png">
         <source path="conesegment_widget.xml"/>
       </feature>
+      <feature id="Ellipsoid" title="Ellipsoid" tooltip="Create a GDML Ellipsoid" icon="icons/GDML/ellipsoid.png">
+        <source path="ellipsoid_widget.xml"/>
+      </feature>
     </group>
   </workbench>
 </plugin>
index 7a30ef3bd38e1a1243e51fcae826ded5756a84b0..43727cf248cef9df30622283f38825a619ce950c 100644 (file)
@@ -60,11 +60,15 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_ShapeAPI.h
     GeomAlgoAPI_Exception.h
     GeomAlgoAPI_Box.h
+    GeomAlgoAPI_Cone.h
     GeomAlgoAPI_Cylinder.h
+    GeomAlgoAPI_Sphere.h
+    GeomAlgoAPI_Torus.h
     GeomAlgoAPI_XAOExport.h
     GeomAlgoAPI_XAOImport.h
     GeomAlgoAPI_Copy.h
     GeomAlgoAPI_ConeSegment.h
+    GeomAlgoAPI_Ellipsoid.h
     GeomAlgoAPI_Symmetry.h
     GeomAlgoAPI_Scale.h
     GeomAlgoAPI_Circ2dBuilder.h
@@ -106,11 +110,15 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_ShapeAPI.cpp
     GeomAlgoAPI_Exception.cpp
     GeomAlgoAPI_Box.cpp
+    GeomAlgoAPI_Cone.cpp
     GeomAlgoAPI_Cylinder.cpp
+    GeomAlgoAPI_Sphere.cpp
+    GeomAlgoAPI_Torus.cpp
     GeomAlgoAPI_XAOExport.cpp
     GeomAlgoAPI_XAOImport.cpp
     GeomAlgoAPI_Copy.cpp
     GeomAlgoAPI_ConeSegment.cpp
+    GeomAlgoAPI_Ellipsoid.cpp
     GeomAlgoAPI_Symmetry.cpp
     GeomAlgoAPI_Scale.cpp
     GeomAlgoAPI_Circ2dBuilder.cpp
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Cone.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Cone.cpp
new file mode 100644 (file)
index 0000000..5d9be8c
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_Cone.cpp
+// Created:     20 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#include <GeomAlgoAPI_Cone.h>
+
+#include <gp_Ax2.hxx>
+
+#include <BRepPrimAPI_MakeCone.hxx>
+
+//=================================================================================================
+GeomAlgoAPI_Cone::GeomAlgoAPI_Cone()
+{
+}
+
+//=================================================================================================
+GeomAlgoAPI_Cone::GeomAlgoAPI_Cone(std::shared_ptr<GeomAPI_Ax2> theAxis,
+                                   const double theBaseRadius,
+                                   const double theTopRadius,
+                                   const double theHeight)
+{
+  myAxis = theAxis;
+  myBaseRadius = theBaseRadius;
+  myTopRadius = theTopRadius;
+  myHeight = theHeight;
+}
+
+//=================================================================================================
+bool GeomAlgoAPI_Cone::check()
+{
+  if (!myAxis) {
+    myError = "Cone builder :: axis is not valid.";
+    return false;
+  } else if (myBaseRadius < Precision::Confusion() && myTopRadius < Precision::Confusion()) {
+    myError = "Cone builder :: base radius and top radius are negative or null.";
+    return false;
+  } else if (myBaseRadius < 0.) {
+    myError = "Cone builder :: base radius is negative.";
+    return false;
+  } else if (myTopRadius < 0.) {
+    myError = "Cone builder :: top radius is negative.";
+    return false;
+  } else if (fabs(myBaseRadius-myTopRadius) < Precision::Confusion()) {
+    myError = "Cone builder :: base radius and top radius are too close.";
+    return false;
+  } else if (myHeight < Precision::Confusion()) {
+    myError = "Cone builder :: height is negative or null.";
+    return false;
+  }
+  return true;
+}
+
+//=================================================================================================
+void GeomAlgoAPI_Cone::build()
+{
+  myCreatedFaces.clear();
+
+  const gp_Ax2& anAxis = myAxis->impl<gp_Ax2>();
+
+  // Construct the torus
+  BRepPrimAPI_MakeCone *aConeMaker =
+    new BRepPrimAPI_MakeCone(anAxis, myBaseRadius, myTopRadius, myHeight);
+
+  aConeMaker->Build();
+
+  if (!aConeMaker->IsDone()) {
+    return;
+  }
+
+  TopoDS_Shape aResult = aConeMaker->Shape();
+  std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+  aShape->setImpl(new TopoDS_Shape(aResult));
+  setShape(aShape);
+
+  // Test on the shapes
+  if (!aShape.get() || aShape->isNull()) {
+    myError = "Torus builder :: resulting shape is null.";
+    return;
+  }
+
+  setImpl(aConeMaker);
+
+  setDone(true);
+}
\ No newline at end of file
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Cone.h b/src/GeomAlgoAPI/GeomAlgoAPI_Cone.h
new file mode 100644 (file)
index 0000000..327ef6b
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_Cone.h
+// Created:     20 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#ifndef GEOMALGOAPI_CONE_H_
+#define GEOMALGOAPI_CONE_H_
+
+#include <GeomAlgoAPI_MakeShape.h>
+
+#include <GeomAPI_Ax2.h>
+
+/**\class GeomAlgoAPI_Cone
+ * \ingroup DataAlgo
+ * \brief Allows to create Cone Primitives
+ */
+class GeomAlgoAPI_Cone : public GeomAlgoAPI_MakeShape
+{
+ public:
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Cone();
+
+  /// Creates a cone.
+  /// \param theAxis The axis of the cone
+  /// \param theBaseRadius The base radius of the cone
+  /// \param theTopRadius The top radius of the cone
+  /// \param theHeight The height of the cone
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Cone(std::shared_ptr<GeomAPI_Ax2> theAxis,
+                                      const double theBaseRadius,
+                                      const double theTopRadius,
+                                      const double theHeight);
+
+  /// Checks if data for the cone construction is OK.
+  GEOMALGOAPI_EXPORT bool check();
+
+  /// Builds the cone.
+  GEOMALGOAPI_EXPORT void build();
+
+ private:
+  std::shared_ptr<GeomAPI_Ax2> myAxis; /// Axis of the cone.
+  double myBaseRadius; /// Base radius of the cone.
+  double myTopRadius; /// Top radius of the cone.
+  double myHeight; /// Height of the cone.
+};
+
+#endif // GEOMALGOAPI_CONE_H_
index 6f3bd6050c852cd05932c79cb9f158b3e1a1d97c..bfdc203b96b1f1ab15c06caa7069f9c954ac9213 100644 (file)
@@ -27,8 +27,6 @@
 
 #include <BRepPrimAPI_MakeCylinder.hxx>
 
-#include <iostream>
-
 //=================================================================================================
 GeomAlgoAPI_Cylinder::GeomAlgoAPI_Cylinder()
 {
index 9fdf285d5b2c2a92658faf454a9e3931be24608b..fcbca3448dc4147fdeb76cc880c534c2c5fb47e5 100644 (file)
@@ -53,7 +53,7 @@ class GeomAlgoAPI_Cylinder : public GeomAlgoAPI_MakeShape
                                           const double theHeight,
                                           const double theAngle);
 
-  /// Checks if data for the cyminder construction is OK.
+  /// Checks if data for the cylinder construction is OK.
   GEOMALGOAPI_EXPORT bool check();
 
   /// Builds the cylinder.
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Ellipsoid.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Ellipsoid.cpp
new file mode 100644 (file)
index 0000000..afa430d
--- /dev/null
@@ -0,0 +1,222 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <GeomAlgoAPI_Ellipsoid.h>
+
+#include <gp_Ax2.hxx>
+#include <gp_Elips.hxx>
+#include <gp_GTrsf.hxx>
+#include <BRepBuilderAPI_GTransform.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <BRepOffsetAPI_Sewing.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepBuilderAPI_MakeSolid.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
+#include <BRepPrimAPI_MakeRevol.hxx>
+
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+
+//=================================================================================================
+GeomAlgoAPI_Ellipsoid::GeomAlgoAPI_Ellipsoid()
+{
+}
+
+//=================================================================================================
+
+GeomAlgoAPI_Ellipsoid::GeomAlgoAPI_Ellipsoid(const double theAx,
+                                             const double theBy,
+                                             const double theCz,
+                                             const double theZCut1,
+                                             const double theZCut2)
+{
+  myAx = theAx;
+  myBy = theBy;
+  myCz = theCz;
+  myZCut1 = theZCut1;
+  myZCut2 = theZCut2;
+}
+
+//=================================================================================================
+bool GeomAlgoAPI_Ellipsoid::check()
+{
+  if (myAx < Precision::Confusion()) {
+    myError = "Ellipsoid builder :: ax is negative or null.";
+    return false;
+  } else if (myBy < Precision::Confusion()) {
+    myError = "Ellipsoid builder :: by is negative or null.";
+    return false;
+  } else if (myCz < Precision::Confusion()) {
+    myError = "Ellipsoid builder :: cz is negative or null.";
+    return false;
+  } else if (myZCut1 < 0.) {
+    myError = "Ellipsoid builder :: zcut1 is negative.";
+    return false;
+  } else if (myZCut2 < 0.) {
+    myError = "Ellipsoid builder :: zcut2 is negative.";
+    return false;
+  } else if (myZCut1 < Precision::Confusion() && myZCut2 < Precision::Confusion()) {
+    myError = "Ellipsoid builder :: zcut1 and zcut2 are null.";
+    return false;
+  }
+
+  return true;
+}
+
+//=================================================================================================
+void GeomAlgoAPI_Ellipsoid::build()
+{
+  myCreatedFaces.clear();
+
+  BRepOffsetAPI_Sewing aSewer;
+  gp_Ax2 aRefAx2;
+  gp_Elips anElips;
+
+  gp_Pnt anOrigin(0., 0., 0.);
+  gp_Dir aDirX(1., 0., 0.);
+  gp_Dir aDirY(0., 1., 0.);
+  gp_Dir aDirZ(0., 0., 1.);
+  gp_Ax1 aZAxis(anOrigin, aDirZ);
+
+  // Calculate the parameters needed to make the edges and the faces
+  // gp_Elips needs the second parameter to be greater than the third (major axis)
+  if (myCz < myAx) {
+    aRefAx2 = gp_Ax2(anOrigin, aDirY, aDirX);
+    anElips = gp_Elips(aRefAx2, myAx / 2., myCz / 2.);
+  } else {
+    aRefAx2 = gp_Ax2(anOrigin, aDirY, aDirZ);
+    anElips = gp_Elips(aRefAx2, myCz / 2., myAx / 2.);
+  }
+
+  double aLowPositionFactor = sqrt(1. - (myZCut1 * myZCut1 * 4. / (myCz * myCz))) / 2.;
+  double aHighPositionFactor = sqrt(1. - (myZCut2 * myZCut2 * 4. / (myCz * myCz))) / 2.;
+
+  double aXEndTop = myAx * aHighPositionFactor;
+  double aXEndBottom = myAx *  aLowPositionFactor;
+
+  // Build the XZ ellipse
+  gp_Pnt anEndPoint1(aXEndTop, 0., myZCut2);
+  gp_Pnt anEndPoint2(aXEndBottom, 0., -myZCut1);
+  BRepBuilderAPI_MakeEdge anElipsBuilder(anElips, anEndPoint1, anEndPoint2);
+  anElipsBuilder.Build();
+  TopoDS_Edge anOuterEdge = anElipsBuilder.Edge();
+
+  // Perform a revolution based on the section to build a simple version of the outer face
+  // (isotropic in XY)
+  BRepPrimAPI_MakeRevol aRevolBuilder(anOuterEdge, aZAxis, 2. * M_PI, Standard_True);
+  if (!aRevolBuilder.IsDone()) {
+    myError = "Ellipsoid builder :: section revolution did not succeed";
+    return;
+  }
+
+  gp_GTrsf aGTrsf;
+  gp_Mat rot (1.,          0., 0.,
+              0., myBy / myAx, 0.,
+              0.,          0., 1.);
+
+  aGTrsf.SetVectorialPart(rot);
+
+  BRepBuilderAPI_GTransform aScaleBuilder(aRevolBuilder.Shape(), aGTrsf, true);
+  if (!aScaleBuilder.IsDone()) {
+    myError = "Ellipsoid builder :: scale did not succeed";
+    return;
+  }
+
+  TopoDS_Face anOuterFace = TopoDS::Face(aScaleBuilder.Shape());
+  aSewer.Add(TopoDS::Face(anOuterFace.Reversed()));
+
+  // Build the high and low ellipse if needed
+  gp_Ax2 aLowAx2;
+  gp_Ax2 aHighAx2;
+  gp_Elips aLowElips;
+  gp_Elips aHighElips;
+  if (myBy < myAx) {
+    if ((myCz / 2. - myZCut1) > Precision::Confusion()) {
+      aLowAx2 = gp_Ax2(gp_Pnt(0., 0., -myZCut1), aDirZ, aDirX);
+      aLowElips = gp_Elips(aLowAx2, aLowPositionFactor * myAx, aLowPositionFactor * myBy);
+    }
+    if ((myCz / 2. - myZCut2) > Precision::Confusion()) {
+      aHighAx2 = gp_Ax2(gp_Pnt(0., 0., myZCut2), aDirZ, aDirX);
+      aHighElips = gp_Elips(aHighAx2, aHighPositionFactor * myAx, aHighPositionFactor * myBy);
+    }
+  } else {
+    if ((myCz / 2. - myZCut1) > Precision::Confusion()) {
+      aLowAx2 = gp_Ax2(gp_Pnt(0., 0., -myZCut1), aDirZ, aDirY);
+      aLowElips = gp_Elips(aLowAx2, aLowPositionFactor * myBy, aLowPositionFactor * myAx);
+    }
+    if ((myCz / 2. - myZCut2) > Precision::Confusion()) {
+      aHighAx2 = gp_Ax2(gp_Pnt(0., 0., myZCut2), aDirZ, aDirY);
+      aHighElips = gp_Elips(aHighAx2, aHighPositionFactor * myBy, aHighPositionFactor * myAx);
+    }
+  }
+
+  // Make higher and lower elliptical faces if needed
+  if ((myCz / 2. - myZCut1) > Precision::Confusion()) {
+    TopoDS_Face aBottomFace;
+    BRepBuilderAPI_MakeEdge aBottomEdgeMk(aLowElips);
+    aBottomEdgeMk.Build();
+    BRepBuilderAPI_MakeWire aBottomWireMk;
+    aBottomWireMk.Add(aBottomEdgeMk.Edge());
+    BRepBuilderAPI_MakeFace aBottomFaceMk(aBottomWireMk.Wire());
+    aBottomFace = aBottomFaceMk.Face();
+    aSewer.Add(TopoDS::Face(aBottomFace.Reversed()));
+  }
+  if ((myCz / 2. - myZCut2) > Precision::Confusion()) {
+    TopoDS_Face aTopFace;
+    BRepBuilderAPI_MakeEdge aTopEdgeMk(aHighElips);
+    aTopEdgeMk.Build();
+    BRepBuilderAPI_MakeWire aTopWireMk;
+    aTopWireMk.Add(aTopEdgeMk.Edge());
+    BRepBuilderAPI_MakeFace aTopFaceMk(aTopWireMk.Wire());
+    aTopFace = aTopFaceMk.Face();
+    aSewer.Add(TopoDS::Face(aTopFace.Reversed()));
+  }
+
+  TopoDS_Shell aShell;
+  aSewer.Perform();
+  if ((myCz / 2. - myZCut2) > Precision::Confusion() ||
+      (myCz / 2. - myZCut1) > Precision::Confusion()) {
+    aShell = TopoDS::Shell(aSewer.SewedShape());
+  } else {
+    TopoDS_Builder aBuilder;
+    aBuilder.MakeShell(aShell);
+    aBuilder.Add(aShell, aSewer.SewedShape());
+  }
+
+  BRepBuilderAPI_MakeSolid *anEllipsoidMk = new BRepBuilderAPI_MakeSolid(aShell);
+  anEllipsoidMk->Build();
+
+  // Store and publish the results
+  std::shared_ptr<GeomAPI_Shape> aResultShape =
+    std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
+  aResultShape->setImpl(new TopoDS_Shape(anEllipsoidMk->Solid()));
+  setShape(aResultShape);
+
+  // Test on the shapes
+  if (!(aResultShape).get() || aResultShape->isNull()) {
+    myError = "Ellipsoid builder  :: resulting shape is null.";
+    return;
+  }
+
+  setImpl(anEllipsoidMk);
+  setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
+
+  setDone(true);
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Ellipsoid.h b/src/GeomAlgoAPI/GeomAlgoAPI_Ellipsoid.h
new file mode 100644 (file)
index 0000000..96a37ea
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GEOMALGOAPI_ELLIPSOID_H_
+#define GEOMALGOAPI_ELLIPSOID_H_
+
+#include <GeomAlgoAPI_MakeShape.h>
+
+/**\class GeomAlgoAPI_Ellipsoid
+ * \ingroup DataAlgo
+ * \brief Allows to create Ellipsoid GDML Primitives.
+ */
+class GeomAlgoAPI_Ellipsoid : public GeomAlgoAPI_MakeShape
+{
+ public:
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Ellipsoid();
+
+  /// Creates a ellipsoid using standard GDML parameters.
+  /// \param theAx X dimension of the ellipsoid.
+  /// \param theBy Y dimension of the ellipsoid.
+  /// \param theCz Z dimension of the ellipsoid.
+  /// \param theZCut1 Lower z cut.
+  /// \param theZCut2 Upper z cut.
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Ellipsoid(const double theAx,
+                                           const double theBy,
+                                           const double theCz,
+                                           const double theZCut1,
+                                           const double theZCut2);
+
+  /// Checks if the set of parameters used to define the ellipsoid are OK.
+  GEOMALGOAPI_EXPORT bool check();
+
+  /// Builds the ellipsoid based on the parameters given in the constructor.
+  GEOMALGOAPI_EXPORT void build();
+
+ private:
+  double myAx; /// X dimension of the ellipsoid.
+  double myBy; /// Y dimension of the ellipsoid.
+  double myCz; /// Z dimension of the ellipsoid.
+  double myZCut1; /// Lower z cut.
+  double myZCut2; /// Upper z cut.
+};
+
+#endif // GEOMALGOAPI_ELLIPSOID_H_
+
index e8aaf3427840a173fabde881da815722063603a2..c8a76a01dbeaea3485077a75d65575ea4202b693 100644 (file)
@@ -68,14 +68,6 @@ bool GeomAlgoAPI_Rotation::check()
         myError = "Rotation builder :: source shape is not valid.";
         return false;
       }
-      if (myAngle < -360.) {
-        myError = "Rotation builder :: angle smaller than -360 degrees.";
-        return false;
-      }
-      if (myAngle > 360.) {
-        myError = "Rotation builder :: angle greater than 360 degrees.";
-        return false;
-      }
       return true;
     }
     case BY_POINTS: {
index 818f52ea6f48e88a9d8227fe1632d12dfd0b1ae1..550bf68f3f0b74d9d9e824b29c685f244d4e172e 100644 (file)
 #include "GeomAlgoAPI_ShapeAPI.h"
 
 #include <GeomAlgoAPI_Box.h>
-#include <GeomAlgoAPI_Cylinder.h>
 #include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_Cone.h>
 #include <GeomAlgoAPI_ConeSegment.h>
+#include <GeomAlgoAPI_Cylinder.h>
 #include <GeomAlgoAPI_EdgeBuilder.h>
 #include <GeomAlgoAPI_Rotation.h>
 #include <GeomAlgoAPI_Scale.h>
+#include <GeomAlgoAPI_Sphere.h>
 #include <GeomAlgoAPI_Symmetry.h>
+#include <GeomAlgoAPI_Torus.h>
 #include <GeomAlgoAPI_Translation.h>
 
 #include <GeomAPI_Lin.h>
@@ -206,6 +209,187 @@ namespace GeomAlgoAPI_ShapeAPI
     return aCylinderAlgo.shape();
   }
 
+  //===============================================================================================
+  std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeAPI::makeSphere(
+      std::shared_ptr<GeomAPI_Pnt> theCenterPoint, double theRadius) throw (GeomAlgoAPI_Exception)
+  {
+    GeomAlgoAPI_Sphere aSphereAlgo(theCenterPoint, theRadius);
+
+    if (!aSphereAlgo.check()) {
+      throw GeomAlgoAPI_Exception(aSphereAlgo.getError());
+    }
+
+    aSphereAlgo.build();
+
+    if(!aSphereAlgo.isDone()) {
+      throw GeomAlgoAPI_Exception(aSphereAlgo.getError());
+    }
+
+    if (!aSphereAlgo.checkValid("Sphere builder")) {
+      throw GeomAlgoAPI_Exception(aSphereAlgo.getError());
+    }
+    return aSphereAlgo.shape();
+  }
+
+  //===============================================================================================
+  std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeAPI::makeSphere(double theRadius)
+      throw (GeomAlgoAPI_Exception)
+  {
+    std::shared_ptr<GeomAPI_Pnt> aCenterPoint =
+      std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(0.,0.,0.));
+
+    GeomAlgoAPI_Sphere aSphereAlgo(aCenterPoint, theRadius);
+
+    if (!aSphereAlgo.check()) {
+      throw GeomAlgoAPI_Exception(aSphereAlgo.getError());
+    }
+
+    aSphereAlgo.build();
+
+    if(!aSphereAlgo.isDone()) {
+      throw GeomAlgoAPI_Exception(aSphereAlgo.getError());
+    }
+
+    if (!aSphereAlgo.checkValid("Sphere builder")) {
+      throw GeomAlgoAPI_Exception(aSphereAlgo.getError());
+    }
+    return aSphereAlgo.shape();
+  }
+
+  //===============================================================================================
+  std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeAPI::makeTorus(
+      std::shared_ptr<GeomAPI_Pnt> theBasePoint,
+      std::shared_ptr<GeomAPI_Edge> theEdge,double theRadius, double theRingRadius)
+      throw (GeomAlgoAPI_Exception)
+  {
+    // Check if the base point is OK
+    if (!theBasePoint) {
+      throw GeomAlgoAPI_Exception("Torus builder :: the base point is not valid.");
+    }
+    // Check if the edge is OK
+    if (!theEdge) {
+      throw GeomAlgoAPI_Exception("Torus builder :: the axis is not valid.");
+    }
+
+    std::shared_ptr<GeomAPI_Ax2> anAxis;
+    anAxis = std::shared_ptr<GeomAPI_Ax2>(new GeomAPI_Ax2(theBasePoint,
+                                                          theEdge->line()->direction()));
+
+    GeomAlgoAPI_Torus aTorusAlgo(anAxis, theRadius, theRingRadius);
+
+    if (!aTorusAlgo.check()) {
+      throw GeomAlgoAPI_Exception(aTorusAlgo.getError());
+    }
+
+    aTorusAlgo.build();
+
+    if(!aTorusAlgo.isDone()) {
+      throw GeomAlgoAPI_Exception(aTorusAlgo.getError());
+    }
+
+    if (!aTorusAlgo.checkValid("Torus builder")) {
+      throw GeomAlgoAPI_Exception(aTorusAlgo.getError());
+    }
+    return aTorusAlgo.shape();
+  }
+
+  //===============================================================================================
+  std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeAPI::makeTorus(double theRadius,
+      double theRingRadius) throw (GeomAlgoAPI_Exception)
+  {
+    std::shared_ptr<GeomAPI_Pnt> aBasePoint =
+      std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(0.,0.,0.));
+    std::shared_ptr<GeomAPI_Edge> aEdge = GeomAlgoAPI_EdgeBuilder::line(0., 0., 1.);
+    std::shared_ptr<GeomAPI_Ax2> anAxis;
+    anAxis = std::shared_ptr<GeomAPI_Ax2>(new GeomAPI_Ax2(aBasePoint,
+                                                          aEdge->line()->direction()));
+
+    GeomAlgoAPI_Torus aTorusAlgo(anAxis, theRadius, theRingRadius);
+
+    if (!aTorusAlgo.check()) {
+      throw GeomAlgoAPI_Exception(aTorusAlgo.getError());
+    }
+
+    aTorusAlgo.build();
+
+    if(!aTorusAlgo.isDone()) {
+      throw GeomAlgoAPI_Exception(aTorusAlgo.getError());
+    }
+
+    if (!aTorusAlgo.checkValid("Torus builder")) {
+      throw GeomAlgoAPI_Exception(aTorusAlgo.getError());
+    }
+    return aTorusAlgo.shape();
+  }
+
+  //===============================================================================================
+  std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeAPI::makeCone(
+      std::shared_ptr<GeomAPI_Pnt> theBasePoint,
+      std::shared_ptr<GeomAPI_Edge> theEdge,
+      double theBaseRadius, double theTopRadius,
+      double theHeight) throw (GeomAlgoAPI_Exception)
+  {
+    // Check if the base point is OK
+    if (!theBasePoint) {
+      throw GeomAlgoAPI_Exception("Cone builder :: the base point is not valid.");
+    }
+    // Check if the edge is OK
+    if (!theEdge) {
+      throw GeomAlgoAPI_Exception("Cone builder :: the axis is not valid.");
+    }
+
+    std::shared_ptr<GeomAPI_Ax2> anAxis;
+    anAxis = std::shared_ptr<GeomAPI_Ax2>(new GeomAPI_Ax2(theBasePoint,
+                                                          theEdge->line()->direction()));
+
+    GeomAlgoAPI_Cone aConeAlgo(anAxis, theBaseRadius, theTopRadius, theHeight);
+
+    if (!aConeAlgo.check()) {
+      throw GeomAlgoAPI_Exception(aConeAlgo.getError());
+    }
+
+    aConeAlgo.build();
+
+    if(!aConeAlgo.isDone()) {
+      throw GeomAlgoAPI_Exception(aConeAlgo.getError());
+    }
+
+    if (!aConeAlgo.checkValid("Cone builder")) {
+      throw GeomAlgoAPI_Exception(aConeAlgo.getError());
+    }
+    return aConeAlgo.shape();
+  }
+
+  //===============================================================================================
+  std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeAPI::makeCone(
+      double theBaseRadius, double theTopRadius,
+      double theHeight) throw (GeomAlgoAPI_Exception)
+  {
+    std::shared_ptr<GeomAPI_Pnt> aBasePoint =
+      std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(0.,0.,0.));
+    std::shared_ptr<GeomAPI_Edge> aEdge = GeomAlgoAPI_EdgeBuilder::line(0., 0., 1.);
+    std::shared_ptr<GeomAPI_Ax2> anAxis;
+    anAxis = std::shared_ptr<GeomAPI_Ax2>(new GeomAPI_Ax2(aBasePoint,
+                                                          aEdge->line()->direction()));
+
+    GeomAlgoAPI_Cone aConeAlgo(anAxis, theBaseRadius, theTopRadius, theHeight);
+
+    if (!aConeAlgo.check()) {
+      throw GeomAlgoAPI_Exception(aConeAlgo.getError());
+    }
+
+    aConeAlgo.build();
+
+    if(!aConeAlgo.isDone()) {
+      throw GeomAlgoAPI_Exception(aConeAlgo.getError());
+    }
+
+    if (!aConeAlgo.checkValid("Cone builder")) {
+      throw GeomAlgoAPI_Exception(aConeAlgo.getError());
+    }
+    return aConeAlgo.shape();
+  }
+
   //===============================================================================================
   std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeAPI::makeTranslation(
     std::shared_ptr<GeomAPI_Shape> theSourceShape,
@@ -503,6 +687,61 @@ namespace GeomAlgoAPI_ShapeAPI
     return GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
   }
 
+  //===============================================================================================
+  std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeAPI::makeMultiRotation(
+    std::shared_ptr<GeomAPI_Shape> theSourceShape,
+    std::shared_ptr<GeomAPI_Ax1> theAxis,
+    const int theNumber)
+  {
+    if (!theAxis) {
+      std::string aError = "Multirotation builder ";
+      aError+=":: the axis is not valid";
+      throw GeomAlgoAPI_Exception(aError);
+    }
+
+    if (theNumber <=0) {
+      std::string aError = "Multirotation builder ";
+      aError+=":: the number of copies is null or negative.";
+      throw GeomAlgoAPI_Exception(aError);
+    }
+
+    double anAngle = 360./theNumber;
+
+    ListOfShape aListOfShape;
+    for (int i=0; i<theNumber; i++) {
+      aListOfShape.
+        push_back(GeomAlgoAPI_ShapeAPI::makeRotation(theSourceShape, theAxis, i*anAngle));
+    }
+    return GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
+  }
+
+  //===============================================================================================
+  std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeAPI::makeMultiRotation(
+    std::shared_ptr<GeomAPI_Shape> theSourceShape,
+    std::shared_ptr<GeomAPI_Ax1> theAxis,
+    const double theStep,
+    const int theNumber)
+  {
+    if (!theAxis) {
+      std::string aError = "Multirotation builder ";
+      aError+=":: the axis is not valid";
+      throw GeomAlgoAPI_Exception(aError);
+    }
+
+    if (theNumber <=0) {
+      std::string aError = "Multirotation builder ";
+      aError+=":: the number of copies is null or negative.";
+      throw GeomAlgoAPI_Exception(aError);
+    }
+
+    ListOfShape aListOfShape;
+    for (int i=0; i<theNumber; i++) {
+      aListOfShape.
+        push_back(GeomAlgoAPI_ShapeAPI::makeRotation(theSourceShape, theAxis, i*theStep));
+    }
+    return GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
+  }
+
   //===============================================================================================
   std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeAPI::makeConeSegment(
     const double theRMin1, const double theRMax1,
index 22b57629d5a08bd3cd4756cc76d0e4819877a550..65b3f1769402a809e729304482396ecb4a54532a 100644 (file)
@@ -85,6 +85,49 @@ public:
   static std::shared_ptr<GeomAPI_Shape> makeCylinder(double theRadius, double theHeight,
                      double theAngle) throw (GeomAlgoAPI_Exception);
 
+  /// Creates a sphere using a center and a radius.
+  /// \param theCenterPoint The center of the sphere
+  /// \param theRadius The radius of the sphere
+  static std::shared_ptr<GeomAPI_Shape> makeSphere(std::shared_ptr<GeomAPI_Pnt> theCenterPoint,
+                     double theRadius) throw (GeomAlgoAPI_Exception);
+
+  /// Creates a sphere using the origin and a radius.
+  /// \param theRadius The radius of the sphere
+  static std::shared_ptr<GeomAPI_Shape> makeSphere(double theRadius)
+                     throw (GeomAlgoAPI_Exception);
+
+  /// Creates a torus using a base point, an axis, a radius and a ring radius.
+  /// \param theBasePoint The center of the torus
+  /// \param theEdge The axis of the torus
+  /// \param theRadius The radius of the torus
+  /// \param theRingRadius The ring radius of the torus
+  static std::shared_ptr<GeomAPI_Shape> makeTorus(std::shared_ptr<GeomAPI_Pnt> theBasePoint,
+                     std::shared_ptr<GeomAPI_Edge> theEdge, double theRadius, double theRingRadius)
+                     throw (GeomAlgoAPI_Exception);
+
+  /// Creates a torus using a radius and a ring radius.
+  /// \param theRadius The radius of the torus
+  /// \param theRingRadius The ring radius of the torus
+  static std::shared_ptr<GeomAPI_Shape> makeTorus(double theRadius, double theRingRadius)
+                     throw (GeomAlgoAPI_Exception);
+
+  /// Creates a cone using a base point, an axis, a base radius, a top radius and a height.
+  /// \param theBasePoint The center of the lower base of the cone
+  /// \param theEdge The axis of the cone
+  /// \param theBaseRadius The base radius of the cone
+  /// \param theTopRadius The top radius of the cone
+  /// \param theHeight The height of the cone
+  static std::shared_ptr<GeomAPI_Shape> makeCone(std::shared_ptr<GeomAPI_Pnt> theBasePoint,
+                     std::shared_ptr<GeomAPI_Edge> theEdge, double theBaseRadius,
+                     double theTopRadius, double theHeight) throw (GeomAlgoAPI_Exception);
+
+  /// Creates a cone using a base radius, a top radius and a height.
+  /// \param theBaseRadius The base radius of the cone
+  /// \param theTopRadius The top radius of the cone
+  /// \param theHeight The height of the cone
+  static std::shared_ptr<GeomAPI_Shape> makeCone(double theBaseRadius, double theTopRadius,
+                     double theHeight) throw (GeomAlgoAPI_Exception);
+
   /// Performs a translation from an axis and a distance.
   /// \param theSourceShape Shape to be moved
   /// \param theAxis Movement axis
@@ -213,6 +256,26 @@ public:
                      const double theSecondStep,
                      const int theSecondNumber) throw (GeomAlgoAPI_Exception);
 
+  /// Performs a multi rotation along one axis and a number of times
+  /// \param[in] theSourceShape Shape to be rotated
+  /// \param[in] theAxis Axis for the rotation
+  /// \param[in] theNumber Number of copies
+  static std::shared_ptr<GeomAPI_Shape> makeMultiRotation(
+                     std::shared_ptr<GeomAPI_Shape> theSourceShape,
+                     std::shared_ptr<GeomAPI_Ax1> theAxis,
+                     const int theNumber);
+
+  /// Performs a multi rotation along one axis, at a step and a number of times
+  /// \param theSourceShape Shape to be moved
+  /// \param[in] theAxis Axis for the rotation
+  /// \param[in] theStep Angle for each rotation
+  /// \param[in] theNumber Number of copies
+  static std::shared_ptr<GeomAPI_Shape> makeMultiRotation(
+                     std::shared_ptr<GeomAPI_Shape> theSourceShape,
+                     std::shared_ptr<GeomAPI_Ax1> theAxis,
+                     const double theStep,
+                     const int theNumber);
+
   /// Creates a cone segment using standard GDML parameters.
   /// \param theRMin1 Inner radius at base of cone
   /// \param theRMax1 Outer radius at base of cone
index 7fcdc7a0e9ecbddcc8eae633ddc8f3498cecf3f7..04ae892e351dcb00e8e2ede067e17185042ca8fe 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "GeomAlgoAPI_SketchBuilder.h"
 
+#include <GeomAPI_Ax1.h>
 #include <GeomAPI_Edge.h>
 #include <GeomAPI_Dir.h>
 #include <GeomAPI_Face.h>
@@ -48,7 +49,9 @@
 #include <Geom2d_Curve.hxx>
 #include <BRepLib_CheckCurveOnSurface.hxx>
 #include <BRep_Tool.hxx>
+#include <Geom_Line.hxx>
 #include <Geom_Plane.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
 #include <GeomLib_IsPlanarSurface.hxx>
 #include <GeomLib_Tool.hxx>
 #include <GeomAPI_ExtremaCurveSurface.hxx>
@@ -915,3 +918,20 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::findShape(
 
   return aResultShape;
 }
+
+//==================================================================================================
+std::shared_ptr<GeomAPI_Dir> GeomAlgoAPI_ShapeTools::buildDirFromAxisAndShape(
+                                    const std::shared_ptr<GeomAPI_Shape> theBaseShape,
+                                    const std::shared_ptr<GeomAPI_Ax1> theAxis)
+{
+  gp_Pnt aCentreOfMassPoint =
+    GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape)->impl<gp_Pnt>();
+  Handle(Geom_Line) aLine = new Geom_Line(theAxis->impl<gp_Ax1>());
+  GeomAPI_ProjectPointOnCurve aPrjTool(aCentreOfMassPoint, aLine);
+  gp_Pnt aPoint = aPrjTool.NearestPoint();
+
+  std::shared_ptr<GeomAPI_Dir> aDir(new GeomAPI_Dir(aCentreOfMassPoint.X()-aPoint.X(),
+                                                    aCentreOfMassPoint.Y()-aPoint.Y(),
+                                                    aCentreOfMassPoint.Z()-aPoint.Z()));
+  return aDir;
+}
index 2e48c96bbf61ee8cb28585d49976fa56a06370c5..168e076098a486fe4bc4384bd97425ea13cbd745 100644 (file)
@@ -29,6 +29,7 @@
 #include <map>
 #include <set>
 
+class GeomAPI_Ax1;
 class GeomAPI_Edge;
 class GeomAPI_Dir;
 class GeomAPI_Face;
@@ -162,6 +163,13 @@ public:
                                     const std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
                                     const std::set<std::shared_ptr<GeomAPI_Shape> >& theShapes);
 
+  /// \brief Returns a dir from a shape and an axis.
+  /// \param[in] theBaseShape shape whose center of mass serves as the starting point of the dir.
+  /// \param[in] theAxis axis that serves as a direction for the dir
+  /// \return dir that builds from center of mass of the base shape and the axis
+  GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Dir> buildDirFromAxisAndShape(
+                                    const std::shared_ptr<GeomAPI_Shape> theBaseShape,
+                                    const std::shared_ptr<GeomAPI_Ax1> theAxis);
 };
 
 #endif
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.cpp
new file mode 100644 (file)
index 0000000..b2642c9
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_Sphere.h
+// Created:     16 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#include <GeomAlgoAPI_Sphere.h>
+
+#include <BRepPrimAPI_MakeSphere.hxx>
+
+//=================================================================================================
+GeomAlgoAPI_Sphere::GeomAlgoAPI_Sphere()
+{
+}
+
+//=================================================================================================
+GeomAlgoAPI_Sphere::GeomAlgoAPI_Sphere(std::shared_ptr<GeomAPI_Pnt> theCenterPoint,
+                                       const double theRadius)
+{
+  myCenterPoint = theCenterPoint;
+  myRadius = theRadius;
+}
+
+//=================================================================================================
+bool GeomAlgoAPI_Sphere::check()
+{
+  if (!myCenterPoint) {
+    myError = "Sphere builder :: center is not valid.";
+    return false;
+  }
+  if (myRadius < Precision::Confusion()) {
+    myError = "Sphere builder :: radius is negative or null.";
+    return false;
+  }
+  return true;
+}
+
+//=================================================================================================
+void GeomAlgoAPI_Sphere::build()
+{
+  myCreatedFaces.clear();
+
+  const gp_Pnt& aCenterPoint = myCenterPoint->impl<gp_Pnt>();
+
+  // Construct the sphere
+  BRepPrimAPI_MakeSphere *aSphereMaker = new BRepPrimAPI_MakeSphere(aCenterPoint, myRadius);
+
+  aSphereMaker->Build();
+
+  if (!aSphereMaker->IsDone()) {
+    return;
+  }
+
+  TopoDS_Shape aResult = aSphereMaker->Shape();
+  std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+  aShape->setImpl(new TopoDS_Shape(aResult));
+  setShape(aShape);
+
+  // Test on the shapes
+  if (!aShape.get() || aShape->isNull()) {
+    myError = "Sphere builder :: resulting shape is null.";
+    return;
+  }
+
+  setImpl(aSphereMaker);
+
+  setDone(true);
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.h b/src/GeomAlgoAPI/GeomAlgoAPI_Sphere.h
new file mode 100644 (file)
index 0000000..f317a26
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_Sphere.h
+// Created:     16 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#ifndef GEOMALGOAPI_SPHERE_H_
+#define GEOMALGOAPI_SPHERE_H_
+
+#include <GeomAlgoAPI_MakeShape.h>
+
+#include <GeomAPI_Pnt.h>
+
+/**\class GeomAlgoAPI_Sphere
+ * \ingroup DataAlgo
+ * \brief Allows to create Sphere Primitives
+ */
+class GeomAlgoAPI_Sphere : public GeomAlgoAPI_MakeShape
+{
+ public:
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Sphere();
+
+  /// Creates a sphere.
+  /// \param theCenterPoint The center point of the sphere
+  /// \param theRadius The radius of the sphere
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Sphere(std::shared_ptr<GeomAPI_Pnt> theCenterPoint,
+                                        const double theRadius);
+
+  /// Checks if data for the sphere construction is OK.
+  GEOMALGOAPI_EXPORT bool check();
+
+  /// Builds the sphere.
+  GEOMALGOAPI_EXPORT void build();
+
+ private:
+  std::shared_ptr<GeomAPI_Pnt> myCenterPoint; /// Center of the sphere.
+  double myRadius;
+};
+
+#endif // GEOMALGOAPI_SPHERE_H_
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Torus.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Torus.cpp
new file mode 100644 (file)
index 0000000..3bc0653
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_Torus.cpp
+// Created:     20 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#include <GeomAlgoAPI_Torus.h>
+
+#include <gp_Ax2.hxx>
+
+#include <BRepPrimAPI_MakeTorus.hxx>
+
+//=================================================================================================
+GeomAlgoAPI_Torus::GeomAlgoAPI_Torus()
+{
+}
+
+//=================================================================================================
+GeomAlgoAPI_Torus::GeomAlgoAPI_Torus(std::shared_ptr<GeomAPI_Ax2> theAxis,
+                                     const double theRadius,
+                                     const double theRingRadius)
+{
+  myAxis = theAxis;
+  myRadius = theRadius;
+  myRingRadius = theRingRadius;
+}
+
+//=================================================================================================
+bool GeomAlgoAPI_Torus::check()
+{
+  if (!myAxis) {
+    myError = "Torus builder :: axis is not valid.";
+    return false;
+  } else if (myRadius < Precision::Confusion()) {
+    myError = "Torus builder :: radius is negative or null.";
+    return false;
+  } else if (myRingRadius < Precision::Confusion()) {
+    myError = "Torus builder :: ring radius is negative or null.";
+    return false;
+  } else if (myRadius < myRingRadius) {
+    myError = "Torus builder :: ring radius is greater than the radius.";
+    return false;
+  }
+  return true;
+}
+
+//=================================================================================================
+void GeomAlgoAPI_Torus::build()
+{
+  myCreatedFaces.clear();
+
+  const gp_Ax2& anAxis = myAxis->impl<gp_Ax2>();
+
+  // Construct the torus
+  BRepPrimAPI_MakeTorus *aTorusMaker =
+    new BRepPrimAPI_MakeTorus(anAxis, myRadius, myRingRadius);
+
+  aTorusMaker->Build();
+
+  if (!aTorusMaker->IsDone()) {
+    return;
+  }
+
+  TopoDS_Shape aResult = aTorusMaker->Shape();
+  std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+  aShape->setImpl(new TopoDS_Shape(aResult));
+  setShape(aShape);
+
+  // Test on the shapes
+  if (!aShape.get() || aShape->isNull()) {
+    myError = "Torus builder :: resulting shape is null.";
+    return;
+  }
+
+  setImpl(aTorusMaker);
+
+  setDone(true);
+}
\ No newline at end of file
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Torus.h b/src/GeomAlgoAPI/GeomAlgoAPI_Torus.h
new file mode 100644 (file)
index 0000000..10f66f5
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_Torus.h
+// Created:     20 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#ifndef GEOMALGOAPI_TORUS_H_
+#define GEOMALGOAPI_TORUS_H_
+
+#include <GeomAlgoAPI_MakeShape.h>
+
+#include <GeomAPI_Ax2.h>
+
+/**\class GeomAlgoAPI_Torus
+ * \ingroup DataAlgo
+ * \brief Allows to create Torus Primitives
+ */
+class GeomAlgoAPI_Torus : public GeomAlgoAPI_MakeShape
+{
+ public:
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Torus();
+
+  /// Creates a torus.
+  /// \param theAxis The axis of the torus
+  /// \param theRadius The radius of the torus
+  /// \param theRingRadius The ring radius of the torus
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Torus(std::shared_ptr<GeomAPI_Ax2> theAxis,
+                                       const double theRadius,
+                                       const double theRingRadius);
+
+  /// Checks if data for the torus construction is OK.
+  GEOMALGOAPI_EXPORT bool check();
+
+  /// Builds the torus.
+  GEOMALGOAPI_EXPORT void build();
+
+ private:
+  std::shared_ptr<GeomAPI_Ax2> myAxis; /// Axis of the torus.
+  double myRadius; /// Radius of the torus.
+  double myRingRadius; /// Ring radius of the torus.
+};
+
+#endif // GEOMALGOAPI_TORUS_H_
\ No newline at end of file
index 344ee30ee36009e59b2dea139d2c2b92d3b907ac..6d97b417e48eda32395f55ed9b6d958507a52a59 100644 (file)
@@ -153,6 +153,12 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext,
     std::shared_ptr<GeomAPI_Shape> aSubShape;
     if (theSubShape.get() && !theContext->shape()->isEqual(theSubShape))
       aSubShape = theSubShape; // the whole context
+    if (aConstruction->isInfinite()) {
+      // For correct naming selection, put the shape into the naming structure.
+      // It seems sub-shapes are not needed: only this shape is (and can be ) selected.
+      TNaming_Builder aBuilder(aSelLab);
+      aBuilder.Generated(theContext->shape()->impl<TopoDS_Shape>());
+    }
     int anIndex = aConstruction->select(theSubShape, owner()->document());
     TDataStd_Integer::Set(aSelLab, anIndex);
   } else if (theContext->groupName() == ModelAPI_ResultPart::group()) {
@@ -298,21 +304,23 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::internalValue(CenterTyp
       }
     }
 
+    std::shared_ptr<Model_ResultConstruction> aConstr =
+      std::dynamic_pointer_cast<Model_ResultConstruction>(context());
+    if (aConstr) {
+      if (aConstr->isInfinite())
+        return aResult; // empty result
+    }
     Handle(TNaming_NamedShape) aSelection;
     if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
       TopoDS_Shape aSelShape = aSelection->Get();
       aResult = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
       aResult->setImpl(new TopoDS_Shape(aSelShape));
-    } else { // for simple construction element: just shape of this construction element
-      std::shared_ptr<Model_ResultConstruction> aConstr =
-        std::dynamic_pointer_cast<Model_ResultConstruction>(context());
-      if (aConstr) {
-        Handle(TDataStd_Integer) anIndex;
-        if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) {
-          if (anIndex->Get() == 0) // it is just reference to construction, nothing is in value
-            return aResult;
-          return aConstr->shape(anIndex->Get(), owner()->document());
-        }
+    } else if (aConstr) { // simple construction element: just shape of this construction element
+      Handle(TDataStd_Integer) anIndex;
+      if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) {
+        if (anIndex->Get() == 0) // it is just reference to construction, nothing is in value
+          return aResult;
+        return aConstr->shape(anIndex->Get(), owner()->document());
       }
     }
   }
index 39fbea9b63c86f22653ac4c03ae89021e1ab1416..4209b2401ccbf509f25e120e8ecc6a8fc593d574 100755 (executable)
@@ -574,7 +574,7 @@ void Model_BodyBuilder::loadNextLevels(std::shared_ptr<GeomAPI_Shape> theShape,
     TopTools_IndexedMapOfShape Edges;
     BRepTools::Map3DEdges(aShape, Edges);
     if (Edges.Extent() == 1) {
-      builder(++theTag)->Generated(Edges.FindKey(1));
+      builder(theTag++)->Generated(Edges.FindKey(1));
       TopExp_Explorer expl(aShape, TopAbs_VERTEX);
       for (; expl.More(); expl.Next()) {
         builder(theTag)->Generated(expl.Current());
@@ -616,42 +616,57 @@ void Model_BodyBuilder::loadNextLevels(std::shared_ptr<GeomAPI_Shape> theShape,
 int findAmbiguities(const TopoDS_Shape&           theShapeIn,
   TopTools_ListOfShape&   theList)
 {
-  int aNumEdges(0);
   theList.Clear();
-  TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors;
-  TopAbs_ShapeEnum aTS(TopAbs_EDGE);
-  TopAbs_ShapeEnum aTA(TopAbs_FACE);
-  TopTools_MapOfShape aMap1, aMap2; // map1 - for edge ancestors; map2 - for keys => edges
-  TopTools_ListOfShape aKeyList;
-  TopExp::MapShapesAndAncestors(theShapeIn, aTS, aTA, subShapeAndAncestors);
-  for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) {
-    const TopoDS_Shape& aKeyEdge1 = subShapeAndAncestors.FindKey(i);
-    const TopTools_ListOfShape& ancestors1 = subShapeAndAncestors.FindFromIndex(i);
-    aMap1.Clear();
-    TopTools_ListIteratorOfListOfShape it(ancestors1);
-    for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1
-    for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) {
-      if (i == j) continue;
-      const TopoDS_Shape& aKeyEdge2 = subShapeAndAncestors.FindKey(j);
-      const TopTools_ListOfShape& ancestors2 = subShapeAndAncestors.FindFromIndex(j);
-      if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) {
-        int aNum (ancestors2.Extent());
-        TopTools_ListIteratorOfListOfShape it(ancestors2);
-        for(;it.More();it.Next())
-          if(aMap1.Contains(it.Value())) aNum--;
-        if(aNum == 0) {
-          if(aMap2.Add(aKeyEdge1))
-            aKeyList.Append(aKeyEdge1);
-          if(aMap2.Add(aKeyEdge2))
-            aKeyList.Append(aKeyEdge2);
+  // edges -> ancestor faces list
+  TopTools_IndexedDataMapOfShapeListOfShape aSubShapeAndAncestors;
+  TopExp::MapShapesAndAncestors(theShapeIn, TopAbs_EDGE, TopAbs_FACE, aSubShapeAndAncestors);
+  // keeps the shapes which are already in the resulting list
+  TopTools_MapOfShape alreadyThere;
+  // map from faces identifier (combination of hash-codes) to list of edges produced such ID
+  NCollection_DataMap<int, NCollection_List<TopoDS_Shape> > aFacesIDs;
+
+  TopTools_IndexedDataMapOfShapeListOfShape::Iterator anAncestorsIter(aSubShapeAndAncestors);
+  for (; anAncestorsIter.More(); anAncestorsIter.Next()) {
+    const TopTools_ListOfShape& ancestors = anAncestorsIter.Value();
+    if (ancestors.Extent() < 2)
+      continue;
+    Standard_Integer anID = 0;
+    for(TopTools_ListIteratorOfListOfShape aFaceIt(ancestors); aFaceIt.More(); aFaceIt.Next()) {
+      anID ^= HashCode(aFaceIt.ChangeValue(), 1990657); // Pierpont prime
+    }
+    if (aFacesIDs.IsBound(anID)) { // there found same edge, check they really have same faces
+      const NCollection_List<TopoDS_Shape>& aSameFaces1 =
+        aSubShapeAndAncestors.FindFromKey(anAncestorsIter.Key());
+      NCollection_List<TopoDS_Shape>::Iterator aSameEdge(aFacesIDs.ChangeFind(anID));
+      for(; aSameEdge.More(); aSameEdge.Next()) {
+        const NCollection_List<TopoDS_Shape>& aSameFaces2 =
+          aSubShapeAndAncestors.FindFromKey(aSameEdge.Value());
+        if (aSameFaces2.Extent() != aSameFaces1.Extent()) // the number of faces is different
+          break;
+
+        NCollection_List<TopoDS_Shape>::Iterator aFaceIter1(aSameFaces1);
+        for(; aFaceIter1.More(); aFaceIter1.Next()) {
+          NCollection_List<TopoDS_Shape>::Iterator aFaceIter2(aSameFaces2);
+          for(; aFaceIter2.More(); aFaceIter2.Next()) {
+            if (aFaceIter1.Value().IsSame(aFaceIter2.Value()))
+              break;
+          }
+          if (!aFaceIter2.More()) // aFaceIter1 contains a face, which is not in aFaceIter2
+            break;
+        }
+        if (!aFaceIter1.More()) { // all the faces are same => put to the result
+          if (alreadyThere.Add(aSameEdge.Value()))
+            theList.Append(aSameEdge.Value());
+          if (alreadyThere.Add(anAncestorsIter.Key()))
+            theList.Append(anAncestorsIter.Key());
         }
       }
-    } // at the end ==> List of edges to be named in addition
+    } else { // ID is unique, just add this edge
+      aFacesIDs.Bind(anID, NCollection_List<TopoDS_Shape>());
+    }
+    aFacesIDs.ChangeFind(anID).Append(anAncestorsIter.Key()); // add to the list anyway
   }
-  aNumEdges = aKeyList.Extent();
-  if(aNumEdges)
-    theList.Assign(aKeyList);
-  return aNumEdges;
+  return theList.Extent();
 }
 
 //=======================================================================
@@ -663,12 +678,13 @@ void Model_BodyBuilder::loadFirstLevel(
   std::string aName;
   if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) {
     TopoDS_Iterator itr(aShape);
-    for (; itr.More(); itr.Next(),theTag++) {
+    for (; itr.More(); itr.Next()) {
       builder(theTag)->Generated(itr.Value());
       TCollection_AsciiString aStr(theTag);
       aName = theName + aStr.ToCString();
       buildName(theTag, aName);
       if(!theName.empty()) buildName(theTag, aName);
+      theTag++;
       if (itr.Value().ShapeType() == TopAbs_COMPOUND ||
         itr.Value().ShapeType() == TopAbs_COMPSOLID)
       {
index 231c0b6ed33290d915c5cfecb54ecccf1c1ed401..c650196d92863db878ad59395ba7b238f860ab73 100755 (executable)
@@ -98,12 +98,13 @@ std::shared_ptr<ModelAPI_ResultBody> Model_ResultCompSolid::subResult(const int
   return mySubs.at(theIndex);
 }
 
-bool Model_ResultCompSolid::isSub(ObjectPtr theObject) const
+bool Model_ResultCompSolid::isSub(ObjectPtr theObject, int& theIndex) const
 {
-  std::vector<std::shared_ptr<ModelAPI_ResultBody> >::const_iterator aSubIter = mySubs.cbegin();
-  for(; aSubIter != mySubs.cend(); aSubIter++)
-    if (*aSubIter == theObject)
-      return true;
+  std::map<ObjectPtr, int>::const_iterator aFound = mySubsMap.find(theObject);
+  if (aFound != mySubsMap.end()) {
+    theIndex = aFound->second;
+    return true;
+  }
   return false;
 }
 
@@ -213,6 +214,7 @@ void Model_ResultCompSolid::updateSubs(const std::shared_ptr<GeomAPI_Shape>& the
       if (mySubs.size() <= aSubIndex) { // it is needed to create a new sub-result
         aSub = anObjects->createBody(this->data(), aSubIndex);
         mySubs.push_back(aSub);
+        mySubsMap[aSub] = int(mySubs.size() - 1);
       } else { // just update shape of this result
         aSub = mySubs[aSubIndex];
       }
@@ -228,6 +230,7 @@ void Model_ResultCompSolid::updateSubs(const std::shared_ptr<GeomAPI_Shape>& the
     while(mySubs.size() > aSubIndex) {
       ResultBodyPtr anErased = *(mySubs.rbegin());
       anErased->setDisabled(anErased, true);
+      mySubsMap.erase(anErased);
       mySubs.pop_back();
     }
     if (aWasEmpty) { // erase all subs
@@ -241,6 +244,7 @@ void Model_ResultCompSolid::updateSubs(const std::shared_ptr<GeomAPI_Shape>& the
         anErased->setDisabled(anErased, true);
       mySubs.pop_back();
     }
+    mySubsMap.clear();
     // redisplay this because result with and without subs are displayed differently
     aECreator->sendUpdated(data()->owner(), EVENT_DISP);
   }
index 7fcf5cc59bae616da02259d634912179528e381b..c748aeeae3800401f93f8124c0d6d19e8378d285 100755 (executable)
@@ -24,6 +24,7 @@
 #include "Model.h"
 #include <ModelAPI_ResultCompSolid.h>
 #include <vector>
+#include <map>
 
 /**\class Model_ResultCompSolid
 * \ingroup DataModel
@@ -35,6 +36,8 @@ class Model_ResultCompSolid : public ModelAPI_ResultCompSolid
 {
   /// Sub-bodies if this is compsolid: zero base index to subs
   std::vector<std::shared_ptr<ModelAPI_ResultBody> > mySubs;
+  /// Also keep map of result to index in mySubs to facilitate speed of access from OB
+  std::map<ObjectPtr, int> mySubsMap;
   /// Flag that stores the previous state of "concealed": if it is changed,
   /// The event must be generated to redisplay this and all subs.
   bool myLastConcealed;
@@ -74,7 +77,8 @@ public:
     bool forTree = false) const;
 
   /// Returns true if feature or reuslt belong to this composite feature as subs
-  MODEL_EXPORT virtual bool isSub(ObjectPtr theObject) const;
+  /// Returns theIndex - zero based index of sub if found
+  MODEL_EXPORT virtual bool isSub(ObjectPtr theObject, int& theIndex) const;
 
   /// Returns the parameters of color definition in the resources config manager
   MODEL_EXPORT virtual void colorConfigInfo(std::string& theSection, std::string& theName,
index 5dbe49d9e27abe5e05f0c00b5e61790278819c8f..89c044cb4ff24e32e9ba24f64c91cdbbabce1347 100644 (file)
@@ -845,10 +845,17 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
       if (aComposite.get()) {
         if (aType == TopAbs_VERTEX || aType == TopAbs_EDGE) {
           // collect all IDs in the name
+          bool isVertexByEdge = false;
           std::map<int, int> anIDs;
           if (!parseSubIndices(aComposite, aSubShapeName,
-              aType == TopAbs_EDGE ? "Edge" : "Vertex", anIDs))
-            return false;
+              aType == TopAbs_EDGE ? "Edge" : "Vertex", anIDs)) {
+            // there is a case when vertex is identified by one circle-edge (2253)
+            if (aType == TopAbs_VERTEX &&
+                parseSubIndices(aComposite, aSubShapeName, "Edge", anIDs))
+              isVertexByEdge = true;
+            else
+              return false;
+          }
 
           const int aSubNum = aComposite->numberOfSubs();
           for(int a = 0; a < aSubNum; a++) {
@@ -865,9 +872,22 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
                   int anOrientation = abs(anIDs[aCompID]);
                   TopoDS_Shape aShape = aRes->shape()->impl<TopoDS_Shape>();
                   if (anOrientation == 1) {
-                    if (aType == aShape.ShapeType()) {
+                    if (!isVertexByEdge && aType == aShape.ShapeType()) {
                       theShapeToBeSelected = aRes->shape();
                       return true;
+                    } else if (isVertexByEdge && aType != aShape.ShapeType()) {
+                      // check that there is only one vertex produces by and circular edge
+                      TopoDS_Shape aShape = aRes->shape()->impl<TopoDS_Shape>();
+                      TopExp_Explorer anExp(aShape, TopAbs_VERTEX);
+                      if (anExp.More())
+                        aShape = anExp.Current();
+                      anExp.Next();
+                      if (!anExp.More() || anExp.Current().IsSame(aShape)) {
+                        std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected(new GeomAPI_Shape());
+                        aShapeToBeSelected->setImpl(new TopoDS_Shape(aShape));
+                        theShapeToBeSelected = aShapeToBeSelected;
+                        return true;
+                      }
                     }
                   } else { // take first or second vertex of the edge
                     TopoDS_Shape aShape = aRes->shape()->impl<TopoDS_Shape>();
index b2558013c8457b824f1015efe7cd2021a6afa226..70abc72d079da83e7de754438e1fadc2b3602daa 100755 (executable)
@@ -45,7 +45,8 @@ public:
                                                          bool forTree = false) const = 0;
 
   /// Returns true if feature or reuslt belong to this composite feature as subs
-  virtual bool isSub(ObjectPtr theObject) const = 0;
+  /// Returns theIndex - zero based index of sub if found
+  virtual bool isSub(ObjectPtr theObject, int& theIndex) const = 0;
 
   /// Set displayed flag to the result and all sub results
   /// \param theDisplay a boolean value
index 9dd0d9d6c7eee1985ad332b2c8a2614e4ca7c4d5..3be42d1f47248161f147105f5eecac93fa1d1534 100755 (executable)
@@ -268,6 +268,7 @@ CompositeFeaturePtr compositeOwner(const FeaturePtr& theFeature)
 
 ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub)
 {
+  int anIndex;
   ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theSub);
   if (aBody.get()) {
     FeaturePtr aFeatureOwner = aBody->document()->feature(aBody);
@@ -276,7 +277,7 @@ ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub)
         aFeatureOwner->results().cbegin();
       for(; aResIter != aFeatureOwner->results().cend(); aResIter++) {
         ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aResIter);
-        if (aComp && aComp->isSub(aBody))
+        if (aComp && aComp->isSub(aBody, anIndex))
           return aComp;
       }
     }
@@ -284,6 +285,25 @@ ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub)
   return ResultCompSolidPtr(); // not found
 }
 
+int compSolidIndex(const ResultPtr& theSub)
+{
+  int anIndex = -1;
+  ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theSub);
+  if (aBody.get()) {
+    FeaturePtr aFeatureOwner = aBody->document()->feature(aBody);
+    if (aFeatureOwner.get()) {
+      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
+        aFeatureOwner->results().cbegin();
+      for(; aResIter != aFeatureOwner->results().cend(); aResIter++) {
+        ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aResIter);
+        if (aComp && aComp->isSub(aBody, anIndex))
+          return anIndex;
+      }
+    }
+  }
+  return anIndex; // not found
+}
+
 bool hasSubResults(const ResultPtr& theResult)
 {
   ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theResult);
index ca3a1d1d8fc8eb55df3b1b687d04e8d37c6dcadb..c119924cb88d16a43106dd9a0de15b69879d9de0 100755 (executable)
@@ -107,6 +107,11 @@ MODELAPI_EXPORT std::shared_ptr<ModelAPI_CompositeFeature> compositeOwner(
  */
 MODELAPI_EXPORT std::shared_ptr<ModelAPI_ResultCompSolid> compSolidOwner(
                                             const std::shared_ptr<ModelAPI_Result>& theSub);
+/*!
+ * Returns index of this result in parent (if parent exists, returned by compSolidOwner)
+ * \returns zero-base index, or -1 if not found
+ */
+MODELAPI_EXPORT int compSolidIndex(const std::shared_ptr<ModelAPI_Result>& theSub);
 
 /*!
 * Returns true if the result contains a not empty list of sub results.
index 3a219f9f18519e386470331687a786799f665be8..60017e8cc972e35af3e319f019f6d01744058b4b 100644 (file)
@@ -133,7 +133,7 @@ void ModelHighAPI_Selection::setName(const std::string& theName)
 
 void ModelHighAPI_Selection::setColor(int theRed, int theGreen, int theBlue)
 {
-  if (myVariantType != VT_ResultSubShapePair)
+  if (myVariantType != VT_ResultSubShapePair || !myResultSubShapePair.first.get())
     return;
 
   AttributeIntArrayPtr aColor =
index f2133770289d05bf79c118a21113a5b3d92c6c5b..d03130b59b2f0b01c2b934f22457d97eb10ea545 100644 (file)
@@ -174,8 +174,10 @@ void fillAttribute(const std::list<ModelHighAPI_Selection> & theValue,
                    const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute)
 {
   theAttribute->clear();
-  for (auto it = theValue.begin(); it != theValue.end(); ++it)
-    theAttribute->append(it->resultSubShapePair().first); // use only context
+  for (auto it = theValue.begin(); it != theValue.end(); ++it) {
+    if (it->resultSubShapePair().first)
+      theAttribute->append(it->resultSubShapePair().first); // use only context
+  }
 }
 
 //--------------------------------------------------------------------------------------
index c5ff1104d9862bd365a99ae021ded888ab69bf59..3fa0b14d0930a8df3d649c640d6a5f51b996feef 100644 (file)
@@ -411,6 +411,11 @@ bool ModuleBase_ModelWidget::processEnter()
   return false;
 }
 
+bool ModuleBase_ModelWidget::processEscape()
+{
+  return false;
+}
+
 bool ModuleBase_ModelWidget::processDelete()
 {
   // we consider that model objects eats delete key in order to
index a1e753fd71c9afd9c9275c75b45ae4123ddc1849..fbd0d6e11ce1d20dd76ad564e75f05244d4382d1 100644 (file)
@@ -243,6 +243,9 @@ Q_OBJECT
   /// Returns true if the event is processed. The default implementation is empty, returns false.
   virtual bool processEnter();
 
+  /// Returns true if the event is processed. The default implementation is empty, returns false.
+  virtual bool processEscape();
+
   /// Returns true if the event is processed. The default implementation is empty, returns false.
   virtual bool processDelete();
 
index a9c27367fe427b41fd6a0b0bcc29de33cfaebb79..be60db9d3b503a620ba69118b8e50af10ef2be79 100644 (file)
@@ -36,6 +36,7 @@
 #include <GeomDataAPI_Point2D.h>
 
 #include <QApplication>
+#include <QKeyEvent>
 #include <QLineEdit>
 #include <QMenu>
 #include <QWidget>
 #include <QDialog>
 #include <QLayout>
 
+// Dialog is redefined to avoid Escape key processing
+class ModuleBase_EditorDialog : public QDialog
+{
+public:
+  ModuleBase_EditorDialog(QWidget* theParent, Qt::WindowFlags theFlags)
+    : QDialog(theParent, theFlags) {}
+  ~ModuleBase_EditorDialog() {}
+
+protected:
+  // Do nothing if key pressed because it is processing on operation manager level
+  virtual void keyPressEvent(QKeyEvent* theEvent) {
+    if (theEvent->key() == Qt::Key_Escape)
+        return;
+    QDialog::keyPressEvent(theEvent);
+  }
+};
+
 ModuleBase_WidgetEditor::ModuleBase_WidgetEditor(QWidget* theParent,
                                                  const Config_WidgetAPI* theData)
 : ModuleBase_WidgetDoubleValue(theParent, theData),
@@ -62,7 +80,7 @@ bool ModuleBase_WidgetEditor::editedValue(double theSpinMinValue, double theSpin
 {
   bool isValueAccepted = false;
 
-  myEditorDialog = new QDialog(QApplication::desktop(), Qt::FramelessWindowHint);
+  myEditorDialog = new ModuleBase_EditorDialog(QApplication::desktop(), Qt::FramelessWindowHint);
 
   QHBoxLayout* aLay = new QHBoxLayout(myEditorDialog);
   aLay->setContentsMargins(2, 2, 2, 2);
@@ -147,9 +165,9 @@ bool ModuleBase_WidgetEditor::showPopupEditor(const bool theSendSignals)
   }
   ModuleBase_Tools::setFocus(mySpinBox, "ModuleBase_WidgetEditor::editedValue");
   mySpinBox->selectAll();
-
-  if (theSendSignals && !myIsEditing)
-    emit enterClicked(this);
+  // enter is processed, so we need not anymore emit clicked signal
+  //if (theSendSignals && !myIsEditing && isValueAccepted)
+  //  emit enterClicked(this);
 
   return isValueAccepted;
 }
@@ -169,3 +187,13 @@ bool ModuleBase_WidgetEditor::processEnter()
 
   return ModuleBase_WidgetDoubleValue::processEnter();
 }
+
+bool ModuleBase_WidgetEditor::processEscape()
+{
+  if (myEditorDialog) {
+    myEditorDialog->reject();
+    return true;
+  }
+
+  return ModuleBase_WidgetDoubleValue::processEscape();
+}
index c8177d56a5bd09032f130746a97d52d136ca6e17..757165744253c45657caa6f25a7e2b52ccdc92ba 100644 (file)
@@ -71,6 +71,9 @@ Q_OBJECT
   /// Returns true if the event is processed.
   virtual bool processEnter();
 
+  /// Reject the current editor dialog if it is shown and returns true.
+  virtual bool processEscape();
+
 private:
   /// Show editor
   /// \param theSpinMinValue a minimal value of popup menu spin box
index b67beffa72b906d13dc901265572b781601b81ae..82f6558b0d7f939ef845ca4600c50ced6703c52d 100644 (file)
@@ -23,12 +23,18 @@ INCLUDE(Common)
 SET(PROJECT_HEADERS
   PrimitivesAPI.h
   PrimitivesAPI_Box.h
+  PrimitivesAPI_Cone.h
   PrimitivesAPI_Cylinder.h
+  PrimitivesAPI_Sphere.h
+  PrimitivesAPI_Torus.h
 )
 
 SET(PROJECT_SOURCES
   PrimitivesAPI_Box.cpp
+  PrimitivesAPI_Cone.cpp
   PrimitivesAPI_Cylinder.cpp
+  PrimitivesAPI_Sphere.cpp
+  PrimitivesAPI_Torus.cpp
 )
 
 SET(PROJECT_LIBRARIES
index 621f6e6b132baf52b06bbc5bb5d6ee127c81107b..055498b86944059fbf2166e293afefe89df9b343 100644 (file)
 
 // shared pointers
 %shared_ptr(PrimitivesAPI_Box)
+%shared_ptr(PrimitivesAPI_Cone)
 %shared_ptr(PrimitivesAPI_Cylinder)
+%shared_ptr(PrimitivesAPI_Sphere)
+%shared_ptr(PrimitivesAPI_Torus)
 
 // all supported interfaces
 %include "PrimitivesAPI_Box.h"
+%include "PrimitivesAPI_Cone.h"
 %include "PrimitivesAPI_Cylinder.h"
+%include "PrimitivesAPI_Sphere.h"
+%include "PrimitivesAPI_Torus.h"
diff --git a/src/PrimitivesAPI/PrimitivesAPI_Cone.cpp b/src/PrimitivesAPI/PrimitivesAPI_Cone.cpp
new file mode 100644 (file)
index 0000000..da564cc
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D -->
+
+// File:        PrimitivesAPI_Cone.cpp
+// Created:     20 Mar 2017
+// Author:      Clarisse Genrault
+
+#include "PrimitivesAPI_Cone.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Selection.h>
+#include <ModelHighAPI_Tools.h>
+
+//==================================================================================================
+PrimitivesAPI_Cone::PrimitivesAPI_Cone(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+//==================================================================================================
+PrimitivesAPI_Cone::PrimitivesAPI_Cone(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                       const ModelHighAPI_Selection& theBasePoint,
+                                       const ModelHighAPI_Selection& theAxis,
+                                       const ModelHighAPI_Double& theBaseRadius,
+                                       const ModelHighAPI_Double& theTopRadius,
+                                       const ModelHighAPI_Double& theHeight)
+: ModelHighAPI_Interface(theFeature)
+{
+  if (initialize()) {
+    fillAttribute(theBasePoint, basePoint());
+    fillAttribute(theAxis, axis());
+    fillAttribute(theBaseRadius, baseRadius());
+    fillAttribute(theTopRadius, topRadius());
+    setHeight(theHeight);
+  }
+}
+
+//==================================================================================================
+PrimitivesAPI_Cone::~PrimitivesAPI_Cone()
+{
+}
+
+//==================================================================================================
+void PrimitivesAPI_Cone::setRadius(const ModelHighAPI_Double& theBaseRadius,
+                                   const ModelHighAPI_Double& theTopRadius)
+{
+  fillAttribute(theBaseRadius, baseRadius());
+  fillAttribute(theTopRadius, topRadius());
+  execute();
+}
+
+//==================================================================================================
+void PrimitivesAPI_Cone::setHeight(const ModelHighAPI_Double& theHeight)
+{
+  fillAttribute(theHeight, height());
+  execute();
+}
+
+//==================================================================================================
+void PrimitivesAPI_Cone::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  theDumper << aBase << " = model.addCone(" << aDocName;
+
+  AttributeSelectionPtr anAttrBasePoint =
+      aBase->selection(PrimitivesPlugin_Cone::BASE_POINT_ID());
+  AttributeSelectionPtr anAttrAxis =
+      aBase->selection(PrimitivesPlugin_Cone::AXIS_ID());
+  theDumper << ", " << anAttrBasePoint << ", " << anAttrAxis;
+
+  AttributeDoublePtr anAttrBaseRadius = aBase->real(PrimitivesPlugin_Cone::BASE_RADIUS_ID());
+  AttributeDoublePtr anAttrTopRadius = aBase->real(PrimitivesPlugin_Cone::TOP_RADIUS_ID());
+  AttributeDoublePtr anAttrHeight = aBase->real(PrimitivesPlugin_Cone::HEIGHT_ID());
+  theDumper << ", " << anAttrBaseRadius << ", " << anAttrTopRadius << ", " << anAttrHeight;
+
+  theDumper << ")" << std::endl;
+}
+
+//==================================================================================================
+ConePtr addCone(const std::shared_ptr<ModelAPI_Document>& thePart,
+                const ModelHighAPI_Selection& theBasePoint,
+                const ModelHighAPI_Selection& theAxis,
+                const ModelHighAPI_Double& theBaseRadius,
+                const ModelHighAPI_Double& theTopRadius,
+                const ModelHighAPI_Double& theHeight)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(PrimitivesAPI_Cone::ID());
+  return ConePtr(new PrimitivesAPI_Cone(aFeature, theBasePoint, theAxis, theBaseRadius,
+                                        theTopRadius, theHeight));
+}
+
+//==================================================================================================
+ConePtr addCone(const std::shared_ptr<ModelAPI_Document>& thePart,
+                const ModelHighAPI_Double& theBaseRadius,
+                const ModelHighAPI_Double& theTopRadius,
+                const ModelHighAPI_Double& theHeight)
+{
+  ModelHighAPI_Selection aBasePoint("VERTEX", "PartSet/Origin");
+  ModelHighAPI_Selection anAxis("EDGE", "PartSet/OZ");
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(PrimitivesAPI_Cone::ID());
+  return ConePtr(new PrimitivesAPI_Cone(aFeature, aBasePoint, anAxis, theBaseRadius,
+                                        theTopRadius, theHeight));
+}
\ No newline at end of file
diff --git a/src/PrimitivesAPI/PrimitivesAPI_Cone.h b/src/PrimitivesAPI/PrimitivesAPI_Cone.h
new file mode 100644 (file)
index 0000000..a83f78a
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D -->
+
+// File:        PrimitivesAPI_Cone.h
+// Created:     20 Mar 2017
+// Author:      Clarisse Genrault
+
+#ifndef PRIMITIVESAPI_CONE_H_
+#define PRIMITIVESAPI_CONE_H_
+
+#include "PrimitivesAPI.h"
+
+#include <PrimitivesPlugin_Cone.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Double;
+class ModelHighAPI_Selection;
+
+/// \class PrimitivesAPI_Cone
+/// \ingroup CPPHighAPI
+/// \brief Interface for primitive Cone feature.
+class PrimitivesAPI_Cone: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  PRIMITIVESAPI_EXPORT
+  explicit PrimitivesAPI_Cone(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  PRIMITIVESAPI_EXPORT
+  explicit PrimitivesAPI_Cone(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const ModelHighAPI_Selection& theBasePoint,
+                              const ModelHighAPI_Selection& theAxis,
+                              const ModelHighAPI_Double& theBaseRadius,
+                              const ModelHighAPI_Double& theTopRadius,
+                              const ModelHighAPI_Double& theHeight);
+
+  /// Destructor.
+  PRIMITIVESAPI_EXPORT
+  virtual ~PrimitivesAPI_Cone();
+
+  INTERFACE_5(PrimitivesPlugin_Cone::ID(),
+             basePoint, PrimitivesPlugin_Cone::BASE_POINT_ID(),
+             ModelAPI_AttributeSelection, /** Base point */,
+             axis, PrimitivesPlugin_Cone::AXIS_ID(),
+             ModelAPI_AttributeSelection, /** Axis */,
+             baseRadius, PrimitivesPlugin_Cone::BASE_RADIUS_ID(),
+             ModelAPI_AttributeDouble, /** Base radius */,
+             topRadius, PrimitivesPlugin_Cone::TOP_RADIUS_ID(),
+             ModelAPI_AttributeDouble, /** Top radius */,
+             height, PrimitivesPlugin_Cone::HEIGHT_ID(),
+             ModelAPI_AttributeDouble, /** Height */)
+
+  /// Set radius
+  PRIMITIVESAPI_EXPORT
+  void setRadius(const ModelHighAPI_Double& theBaseRadius,
+                 const ModelHighAPI_Double& theTopRadius);
+
+  /// Set height
+  PRIMITIVESAPI_EXPORT
+  void setHeight(const ModelHighAPI_Double& theHeight);
+
+  /// Dump wrapped feature
+  PRIMITIVESAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on primitive Cone object
+typedef std::shared_ptr<PrimitivesAPI_Cone> ConePtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create primitive Cone feature.
+PRIMITIVESAPI_EXPORT
+ConePtr addCone(const std::shared_ptr<ModelAPI_Document>& thePart,
+                const ModelHighAPI_Selection& theBasePoint,
+                const ModelHighAPI_Selection& theAxis,
+                const ModelHighAPI_Double& theBaseRadius,
+                const ModelHighAPI_Double& theTopRadius,
+                const ModelHighAPI_Double& theHeight);
+
+/// \ingroup CPPHighAPI
+/// \brief Create primitive Cone feature.
+PRIMITIVESAPI_EXPORT
+ConePtr addCone(const std::shared_ptr<ModelAPI_Document>& thePart,
+                const ModelHighAPI_Double& theBaseRadius,
+                const ModelHighAPI_Double& theTopRadius,
+                const ModelHighAPI_Double& theHeight);
+
+#endif // PRIMITIVESAPI_CONE_H_
index 9dcc5869485362a73991f730a9163dba0c747edf..141f0e41aa62e106501fd9ac5cf89b39ac67bd7e 100644 (file)
@@ -24,8 +24,6 @@
 #include <ModelHighAPI_Selection.h>
 #include <ModelHighAPI_Tools.h>
 
-#include <iostream>
-
 //==================================================================================================
 PrimitivesAPI_Cylinder::PrimitivesAPI_Cylinder(const std::shared_ptr<ModelAPI_Feature>& theFeature)
 : ModelHighAPI_Interface(theFeature)
@@ -35,10 +33,10 @@ PrimitivesAPI_Cylinder::PrimitivesAPI_Cylinder(const std::shared_ptr<ModelAPI_Fe
 
 //==================================================================================================
 PrimitivesAPI_Cylinder::PrimitivesAPI_Cylinder(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                                     const ModelHighAPI_Selection& theBasePoint,
-                                  const ModelHighAPI_Selection& theAxis,
-                                  const ModelHighAPI_Double& theRadius,
-                                  const ModelHighAPI_Double& theHeight)
+                                               const ModelHighAPI_Selection& theBasePoint,
+                                               const ModelHighAPI_Selection& theAxis,
+                                               const ModelHighAPI_Double& theRadius,
+                                               const ModelHighAPI_Double& theHeight)
 : ModelHighAPI_Interface(theFeature)
 {
   if (initialize()) {
@@ -51,11 +49,11 @@ PrimitivesAPI_Cylinder::PrimitivesAPI_Cylinder(const std::shared_ptr<ModelAPI_Fe
 
 //==================================================================================================
 PrimitivesAPI_Cylinder::PrimitivesAPI_Cylinder(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                                     const ModelHighAPI_Selection& theBasePoint,
-                                  const ModelHighAPI_Selection& theAxis,
-                                  const ModelHighAPI_Double& theRadius,
-                                  const ModelHighAPI_Double& theHeight,
-                                  const ModelHighAPI_Double& theAngle)
+                                               const ModelHighAPI_Selection& theBasePoint,
+                                               const ModelHighAPI_Selection& theAxis,
+                                               const ModelHighAPI_Double& theRadius,
+                                               const ModelHighAPI_Double& theHeight,
+                                               const ModelHighAPI_Double& theAngle)
 : ModelHighAPI_Interface(theFeature)
 {
   if (initialize()) {
index f7ead27569f8861a24946febddb7e136ffb33e11..4261135476655e7f3e931544537f1472ce3e0172 100644 (file)
@@ -31,9 +31,9 @@
 class ModelHighAPI_Double;
 class ModelHighAPI_Selection;
 
-/// \class PrimitivesAPI_Box
+/// \class PrimitivesAPI_Cylinder
 /// \ingroup CPPHighAPI
-/// \brief Interface for primitive Box feature.
+/// \brief Interface for primitive Cylinder feature.
 class PrimitivesAPI_Cylinder: public ModelHighAPI_Interface
 {
 public:
@@ -41,13 +41,6 @@ public:
   PRIMITIVESAPI_EXPORT
   explicit PrimitivesAPI_Cylinder(const std::shared_ptr<ModelAPI_Feature>& theFeature);
 
-  /// Constructor with values.
-  /*PRIMITIVESAPI_EXPORT
-  explicit PrimitivesAPI_Cylinder(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                             const ModelHighAPI_Double& theDx,
-                             const ModelHighAPI_Double& theDy,
-                             const ModelHighAPI_Double& theDz);*/
-
   /// Constructor with values.
   PRIMITIVESAPI_EXPORT
   explicit PrimitivesAPI_Cylinder(const std::shared_ptr<ModelAPI_Feature>& theFeature,
@@ -73,15 +66,15 @@ public:
              creationMethod, PrimitivesPlugin_Cylinder::CREATION_METHOD(),
              ModelAPI_AttributeString, /** Creation method */,
              basePoint, PrimitivesPlugin_Cylinder::BASE_POINT_ID(),
-             ModelAPI_AttributeSelection, /** Dimension in X */,
+             ModelAPI_AttributeSelection, /** Base point */,
              axis, PrimitivesPlugin_Cylinder::AXIS_ID(),
-             ModelAPI_AttributeSelection, /** Dimension in Y */,
+             ModelAPI_AttributeSelection, /** Axis */,
              radius, PrimitivesPlugin_Cylinder::RADIUS_ID(),
-             ModelAPI_AttributeDouble, /** Dimension in Z */,
+             ModelAPI_AttributeDouble, /** Radius */,
              height, PrimitivesPlugin_Cylinder::HEIGHT_ID(),
-             ModelAPI_AttributeDouble, /** First point */,
+             ModelAPI_AttributeDouble, /** Height */,
              angle, PrimitivesPlugin_Cylinder::ANGLE_ID(),
-             ModelAPI_AttributeDouble, /** Second point */)
+             ModelAPI_AttributeDouble, /** Angle */)
 
   /// Set dimensions
   PRIMITIVESAPI_EXPORT
@@ -93,11 +86,11 @@ public:
   virtual void dump(ModelHighAPI_Dumper& theDumper) const;
 };
 
-/// Pointer on primitive Box object
+/// Pointer on primitive Cylinder object
 typedef std::shared_ptr<PrimitivesAPI_Cylinder> CylinderPtr;
 
 /// \ingroup CPPHighAPI
-/// \brief Create primitive Box feature.
+/// \brief Create primitive Cylinder feature.
 PRIMITIVESAPI_EXPORT
 CylinderPtr addCylinder(const std::shared_ptr<ModelAPI_Document>& thePart,
                         const ModelHighAPI_Selection& theBasePoint,
@@ -106,7 +99,7 @@ CylinderPtr addCylinder(const std::shared_ptr<ModelAPI_Document>& thePart,
                         const ModelHighAPI_Double& theHeight);
 
 /// \ingroup CPPHighAPI
-/// \brief Create primitive Box feature.
+/// \brief Create primitive Cylinder feature.
 PRIMITIVESAPI_EXPORT
 CylinderPtr addCylinder(const std::shared_ptr<ModelAPI_Document>& thePart,
                         const ModelHighAPI_Selection& theBasePoint,
@@ -116,14 +109,14 @@ CylinderPtr addCylinder(const std::shared_ptr<ModelAPI_Document>& thePart,
                         const ModelHighAPI_Double& theAngle);
 
 /// \ingroup CPPHighAPI
-/// \brief Create primitive Box feature.
+/// \brief Create primitive Cylinder feature.
 PRIMITIVESAPI_EXPORT
 CylinderPtr addCylinder(const std::shared_ptr<ModelAPI_Document>& thePart,
                         const ModelHighAPI_Double& theRadius,
                         const ModelHighAPI_Double& theHeight);
 
 /// \ingroup CPPHighAPI
-/// \brief Create primitive Box feature.
+/// \brief Create primitive Cylinder feature.
 PRIMITIVESAPI_EXPORT
 CylinderPtr addCylinder(const std::shared_ptr<ModelAPI_Document>& thePart,
                         const ModelHighAPI_Double& theRadius,
diff --git a/src/PrimitivesAPI/PrimitivesAPI_Sphere.cpp b/src/PrimitivesAPI/PrimitivesAPI_Sphere.cpp
new file mode 100644 (file)
index 0000000..dc8b6ab
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D -->
+
+// File:        PrimitivesAPI_Sphere.h
+// Created:     16 Mar 2017
+// Author:      Clarisse Genrault
+
+#include "PrimitivesAPI_Sphere.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Selection.h>
+#include <ModelHighAPI_Tools.h>
+
+//==================================================================================================
+PrimitivesAPI_Sphere::PrimitivesAPI_Sphere(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+//==================================================================================================
+PrimitivesAPI_Sphere::PrimitivesAPI_Sphere(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                           const ModelHighAPI_Selection& theCenterPoint,
+                                           const ModelHighAPI_Double& theRadius)
+: ModelHighAPI_Interface(theFeature)
+{
+  if (initialize()) {
+    fillAttribute(theCenterPoint, centerPoint());
+    setRadius(theRadius);
+  }
+}
+
+//==================================================================================================
+PrimitivesAPI_Sphere::~PrimitivesAPI_Sphere()
+{
+}
+
+//==================================================================================================
+void PrimitivesAPI_Sphere::setCenterPoint(const ModelHighAPI_Selection& theCenterPoint)
+{
+  fillAttribute(theCenterPoint, centerPoint());
+  execute();
+}
+
+//==================================================================================================
+void PrimitivesAPI_Sphere::setRadius(const ModelHighAPI_Double& theRadius)
+{
+  fillAttribute(theRadius, radius());
+  execute();
+}
+
+//==================================================================================================
+void PrimitivesAPI_Sphere::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  theDumper << aBase << " = model.addSphere(" << aDocName;
+
+  AttributeSelectionPtr anAttrCenterPoint =
+      aBase->selection(PrimitivesPlugin_Sphere::CENTER_POINT_ID());
+  AttributeDoublePtr anAttrRadius = aBase->real(PrimitivesPlugin_Sphere::RADIUS_ID());
+  theDumper << ", " << anAttrCenterPoint << ", " << anAttrRadius;
+
+  theDumper << ")" << std::endl;
+}
+
+//==================================================================================================
+SpherePtr addSphere(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const ModelHighAPI_Selection& theCenterPoint,
+                    const ModelHighAPI_Double& theRadius)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(PrimitivesAPI_Sphere::ID());
+  return SpherePtr(new PrimitivesAPI_Sphere(aFeature, theCenterPoint, theRadius));
+}
+
+//==================================================================================================
+SpherePtr addSphere(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const ModelHighAPI_Double& theRadius)
+{
+  ModelHighAPI_Selection aCenterPoint("VERTEX", "PartSet/Origin");
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(PrimitivesAPI_Sphere::ID());
+  return SpherePtr(new PrimitivesAPI_Sphere(aFeature, aCenterPoint, theRadius));
+}
diff --git a/src/PrimitivesAPI/PrimitivesAPI_Sphere.h b/src/PrimitivesAPI/PrimitivesAPI_Sphere.h
new file mode 100644 (file)
index 0000000..0374469
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D -->
+
+// File:        PrimitivesAPI_Sphere.h
+// Created:     16 Mar 2017
+// Author:      Clarisse Genrault
+
+#ifndef PRIMITIVESAPI_SPHERE_H_
+#define PRIMITIVESAPI_SPHERE_H_
+
+#include "PrimitivesAPI.h"
+
+#include <PrimitivesPlugin_Sphere.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Double;
+class ModelHighAPI_Selection;
+
+/// \class PrimitivesAPI_Sphere
+/// \ingroup CPPHighAPI
+/// \brief Interface for primitive Sphere feature.
+class PrimitivesAPI_Sphere: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  PRIMITIVESAPI_EXPORT
+  explicit PrimitivesAPI_Sphere(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  PRIMITIVESAPI_EXPORT
+  explicit PrimitivesAPI_Sphere(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                const ModelHighAPI_Selection& theCenterPoint,
+                                const ModelHighAPI_Double& theRadius);
+
+  /// Destructor.
+  PRIMITIVESAPI_EXPORT
+  virtual ~PrimitivesAPI_Sphere();
+
+  INTERFACE_2(PrimitivesPlugin_Sphere::ID(),
+             centerPoint, PrimitivesPlugin_Sphere::CENTER_POINT_ID(),
+             ModelAPI_AttributeSelection, /** Center point */,
+             radius, PrimitivesPlugin_Sphere::RADIUS_ID(),
+             ModelAPI_AttributeDouble, /** Radius */)
+
+  /// Set center point
+  PRIMITIVESAPI_EXPORT
+  void setCenterPoint(const ModelHighAPI_Selection& theCenterPoint);
+
+  /// Set radius
+  PRIMITIVESAPI_EXPORT
+  void setRadius(const ModelHighAPI_Double& theRadius);
+
+  /// Dump wrapped feature
+  PRIMITIVESAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on primitive Sphere object
+typedef std::shared_ptr<PrimitivesAPI_Sphere> SpherePtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create primitive Sphere feature.
+PRIMITIVESAPI_EXPORT
+SpherePtr addSphere(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const ModelHighAPI_Selection& theCenterPoint,
+                    const ModelHighAPI_Double& theRadius);
+
+/// \ingroup CPPHighAPI
+/// \brief Create primitive Sphere feature.
+PRIMITIVESAPI_EXPORT
+SpherePtr addSphere(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const ModelHighAPI_Double& theRadius);
+
+#endif // PRIMITIVESAPI_SPHERE_H_
diff --git a/src/PrimitivesAPI/PrimitivesAPI_Torus.cpp b/src/PrimitivesAPI/PrimitivesAPI_Torus.cpp
new file mode 100644 (file)
index 0000000..825c2b9
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D -->
+
+// File:        PrimitivesAPI_Torus.cpp
+// Created:     20 Mar 2017
+// Author:      Clarisse Genrault
+
+#include "PrimitivesAPI_Torus.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Selection.h>
+#include <ModelHighAPI_Tools.h>
+
+//==================================================================================================
+PrimitivesAPI_Torus::PrimitivesAPI_Torus(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+//==================================================================================================
+PrimitivesAPI_Torus::PrimitivesAPI_Torus(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                       const ModelHighAPI_Selection& theBasePoint,
+                                       const ModelHighAPI_Selection& theAxis,
+                                       const ModelHighAPI_Double& theRadius,
+                                       const ModelHighAPI_Double& theRingRadius)
+: ModelHighAPI_Interface(theFeature)
+{
+  if (initialize()) {
+    fillAttribute(theBasePoint, basePoint());
+    fillAttribute(theAxis, axis());
+    setRadius(theRadius, theRingRadius);
+  }
+}
+
+//==================================================================================================
+PrimitivesAPI_Torus::~PrimitivesAPI_Torus()
+{
+}
+
+//==================================================================================================
+void PrimitivesAPI_Torus::setRadius(const ModelHighAPI_Double& theRadius,
+                                    const ModelHighAPI_Double& theRingRadius)
+{
+  fillAttribute(theRadius, radius());
+  fillAttribute(theRingRadius, ringRadius());
+  execute();
+}
+
+//==================================================================================================
+void PrimitivesAPI_Torus::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  theDumper << aBase << " = model.addTorus(" << aDocName;
+
+  AttributeSelectionPtr anAttrBasePoint =
+      aBase->selection(PrimitivesPlugin_Torus::BASE_POINT_ID());
+  AttributeSelectionPtr anAttrAxis =
+      aBase->selection(PrimitivesPlugin_Torus::AXIS_ID());
+  theDumper << ", " << anAttrBasePoint << ", " << anAttrAxis;
+
+  AttributeDoublePtr anAttrRadius = aBase->real(PrimitivesPlugin_Torus::RADIUS_ID());
+  AttributeDoublePtr anAttrRingRadius = aBase->real(PrimitivesPlugin_Torus::RING_RADIUS_ID());
+  theDumper << ", " << anAttrRadius << ", " << anAttrRingRadius;
+
+  theDumper << ")" << std::endl;
+}
+
+//==================================================================================================
+TorusPtr addTorus(const std::shared_ptr<ModelAPI_Document>& thePart,
+                  const ModelHighAPI_Selection& theBasePoint,
+                  const ModelHighAPI_Selection& theAxis,
+                  const ModelHighAPI_Double& theRadius,
+                  const ModelHighAPI_Double& theRingRadius)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(PrimitivesAPI_Torus::ID());
+  return TorusPtr(new PrimitivesAPI_Torus(aFeature, theBasePoint, theAxis,
+                                          theRadius, theRingRadius));
+}
+
+//==================================================================================================
+TorusPtr addTorus(const std::shared_ptr<ModelAPI_Document>& thePart,
+                  const ModelHighAPI_Double& theRadius,
+                  const ModelHighAPI_Double& theRingRadius)
+{
+  ModelHighAPI_Selection aBasePoint("VERTEX", "PartSet/Origin");
+  ModelHighAPI_Selection anAxis("EDGE", "PartSet/OZ");
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(PrimitivesAPI_Torus::ID());
+  return TorusPtr(new PrimitivesAPI_Torus(aFeature, aBasePoint, anAxis, theRadius, theRingRadius));
+}
\ No newline at end of file
diff --git a/src/PrimitivesAPI/PrimitivesAPI_Torus.h b/src/PrimitivesAPI/PrimitivesAPI_Torus.h
new file mode 100644 (file)
index 0000000..32c7d10
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D -->
+
+// File:        PrimitivesAPI_Torus.h
+// Created:     20 Mar 2017
+// Author:      Clarisse Genrault
+
+#ifndef PRIMITIVESAPI_TORUS_H_
+#define PRIMITIVESAPI_TORUS_H_
+
+#include "PrimitivesAPI.h"
+
+#include <PrimitivesPlugin_Torus.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Double;
+class ModelHighAPI_Selection;
+
+/// \class PrimitivesAPI_Torus
+/// \ingroup CPPHighAPI
+/// \brief Interface for primitive Cone feature.
+class PrimitivesAPI_Torus: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  PRIMITIVESAPI_EXPORT
+  explicit PrimitivesAPI_Torus(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  PRIMITIVESAPI_EXPORT
+  explicit PrimitivesAPI_Torus(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                               const ModelHighAPI_Selection& theBasePoint,
+                               const ModelHighAPI_Selection& theAxis,
+                               const ModelHighAPI_Double& theRadius,
+                               const ModelHighAPI_Double& theRingRadius);
+
+  /// Destructor.
+  PRIMITIVESAPI_EXPORT
+  virtual ~PrimitivesAPI_Torus();
+
+  INTERFACE_4(PrimitivesPlugin_Torus::ID(),
+             basePoint, PrimitivesPlugin_Torus::BASE_POINT_ID(),
+             ModelAPI_AttributeSelection, /** Base point */,
+             axis, PrimitivesPlugin_Torus::AXIS_ID(),
+             ModelAPI_AttributeSelection, /** Axis */,
+             radius, PrimitivesPlugin_Torus::RADIUS_ID(),
+             ModelAPI_AttributeDouble, /** Radius */,
+             ringRadius, PrimitivesPlugin_Torus::RING_RADIUS_ID(),
+             ModelAPI_AttributeDouble, /** Ring radius */)
+
+  /// Set radius
+  PRIMITIVESAPI_EXPORT
+  void setRadius(const ModelHighAPI_Double& theRadius,
+                 const ModelHighAPI_Double& theRingRadius);
+
+  /// Dump wrapped feature
+  PRIMITIVESAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on primitive Cone object
+typedef std::shared_ptr<PrimitivesAPI_Torus> TorusPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create primitive Cone feature.
+PRIMITIVESAPI_EXPORT
+TorusPtr addTorus(const std::shared_ptr<ModelAPI_Document>& thePart,
+                  const ModelHighAPI_Selection& theBasePoint,
+                  const ModelHighAPI_Selection& theAxis,
+                  const ModelHighAPI_Double& theRadius,
+                  const ModelHighAPI_Double& theRingRadius);
+
+/// \ingroup CPPHighAPI
+/// \brief Create primitive Cone feature.
+PRIMITIVESAPI_EXPORT
+TorusPtr addTorus(const std::shared_ptr<ModelAPI_Document>& thePart,
+                  const ModelHighAPI_Double& theRadius,
+                  const ModelHighAPI_Double& theRingRadius);
+
+#endif // PRIMITIVESAPI_TORUS_H_
index 8ea33c31f429c2350abe885cefe4ac8efbd29855..9de3a6184df4ba8b88793d66326ff07997e89d6d 100644 (file)
@@ -25,6 +25,9 @@
 
   #include "PrimitivesAPI.h"
   #include "PrimitivesAPI_Box.h"
+  #include "PrimitivesAPI_Cone.h"
   #include "PrimitivesAPI_Cylinder.h"
+  #include "PrimitivesAPI_Sphere.h"
+  #include "PrimitivesAPI_Torus.h"
 
 #endif // PRIMITIVESAPI_SWIG_H_
index fdfff5368835179bb681496ddb98bb99faf13122..7a2d16e4d9b21d1a464106c0f9c49858beac6286 100644 (file)
@@ -22,19 +22,28 @@ SET(PROJECT_HEADERS
     PrimitivesPlugin.h
     PrimitivesPlugin_Plugin.h
     PrimitivesPlugin_Box.h
+    PrimitivesPlugin_Cone.h
     PrimitivesPlugin_Cylinder.h
+    PrimitivesPlugin_Sphere.h
+    PrimitivesPlugin_Torus.h
 )
 
 SET(PROJECT_SOURCES
     PrimitivesPlugin_Plugin.cpp
     PrimitivesPlugin_Box.cpp
+    PrimitivesPlugin_Cone.cpp
     PrimitivesPlugin_Cylinder.cpp
+    PrimitivesPlugin_Sphere.cpp
+    PrimitivesPlugin_Torus.cpp
 )
 
 SET(XML_RESOURCES
   plugin-Primitives.xml
   box_widget.xml
+  cone_widget.xml
   cylinder_widget.xml
+  sphere_widget.xml
+  torus_widget.xml
 )
 
 INCLUDE_DIRECTORIES(
diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Cone.cpp b/src/PrimitivesPlugin/PrimitivesPlugin_Cone.cpp
new file mode 100644 (file)
index 0000000..2c29165
--- /dev/null
@@ -0,0 +1,172 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D
+
+// File:        PrimitivesPlugin_Cone.cpp
+// Created:     17 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#include <PrimitivesPlugin_Cone.h>
+
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Lin.h>
+#include <GeomAPI_ShapeExplorer.h>
+
+#include <GeomAlgoAPI_PointBuilder.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+
+#include <sstream>
+
+//=================================================================================================
+PrimitivesPlugin_Cone::PrimitivesPlugin_Cone()
+{
+}
+
+//=================================================================================================
+void PrimitivesPlugin_Cone::initAttributes()
+{
+  data()->addAttribute(PrimitivesPlugin_Cone::BASE_POINT_ID(),
+                       ModelAPI_AttributeSelection::typeId());
+  data()->addAttribute(PrimitivesPlugin_Cone::AXIS_ID(),
+                       ModelAPI_AttributeSelection::typeId());
+
+  data()->addAttribute(PrimitivesPlugin_Cone::BASE_RADIUS_ID(),
+                       ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(PrimitivesPlugin_Cone::TOP_RADIUS_ID(),
+                       ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(PrimitivesPlugin_Cone::HEIGHT_ID(),
+                       ModelAPI_AttributeDouble::typeId());
+
+  // Initialize the base point of the cone at the origin if the base point is not filled.
+  AttributeSelectionPtr aCenterPoint =
+    data()->selection(PrimitivesPlugin_Cone::BASE_POINT_ID());
+  if (!aCenterPoint->isInitialized()) {
+    ObjectPtr aPointObj = ModelAPI_Session::get()->moduleDocument()
+      ->objectByName(ModelAPI_ResultConstruction::group(), "Origin");
+    if (aPointObj.get()) {
+      ResultPtr aPointRes = std::dynamic_pointer_cast<ModelAPI_Result>(aPointObj);
+      aCenterPoint->setValue(aPointRes, std::shared_ptr<GeomAPI_Shape>());
+    }
+  }
+
+  // Initialize the axis at the OZ axis if the axis is not filled.
+  AttributeSelectionPtr anAxis = data()->selection(PrimitivesPlugin_Cone::AXIS_ID());
+  if (!anAxis->isInitialized()) {
+    ObjectPtr anAxisObj = ModelAPI_Session::get()->moduleDocument()
+      ->objectByName(ModelAPI_ResultConstruction::group(), "OZ");
+    if (anAxisObj.get()) {
+      ResultPtr anAxisRes = std::dynamic_pointer_cast<ModelAPI_Result>(anAxisObj);
+      anAxis->setValue(anAxisRes, std::shared_ptr<GeomAPI_Shape>());
+    }
+  }
+}
+
+//=================================================================================================
+void PrimitivesPlugin_Cone::execute()
+{
+  // Getting base point.
+  std::shared_ptr<GeomAPI_Pnt> aBasePoint;
+  std::shared_ptr<ModelAPI_AttributeSelection> aPointRef =
+    selection(PrimitivesPlugin_Cone::BASE_POINT_ID());
+  if (aPointRef.get() != NULL) {
+    GeomShapePtr aShape1 = aPointRef->value();
+    if (!aShape1.get()) {
+      aShape1 = aPointRef->context()->shape();
+    }
+    if (aShape1) {
+       aBasePoint = GeomAlgoAPI_PointBuilder::point(aShape1);
+    }
+  }
+
+  // Getting axis.
+  std::shared_ptr<GeomAPI_Ax2> anAxis;
+  std::shared_ptr<GeomAPI_Edge> anEdge;
+  std::shared_ptr<ModelAPI_AttributeSelection> anEdgeRef =
+    selection(PrimitivesPlugin_Cone::AXIS_ID());
+  if(anEdgeRef && anEdgeRef->value() && anEdgeRef->value()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anEdgeRef->value()));
+  } else if (anEdgeRef && !anEdgeRef->value() && anEdgeRef->context() &&
+             anEdgeRef->context()->shape() && anEdgeRef->context()->shape()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anEdgeRef->context()->shape()));
+  }
+  if(anEdge) {
+    anAxis = std::shared_ptr<GeomAPI_Ax2>(new GeomAPI_Ax2(aBasePoint,
+                                                          anEdge->line()->direction()));
+  }
+
+  // Getting base radius, top radius and height
+  double aBaseRadius = real(PrimitivesPlugin_Cone::BASE_RADIUS_ID())->value();
+  double aTopRadius = real(PrimitivesPlugin_Cone::TOP_RADIUS_ID())->value();
+  double aHeight = real(PrimitivesPlugin_Cone::HEIGHT_ID())->value();
+
+  std::shared_ptr<GeomAlgoAPI_Cone> aConeAlgo =
+    std::shared_ptr<GeomAlgoAPI_Cone>(new GeomAlgoAPI_Cone(anAxis,
+                                                           aBaseRadius,
+                                                           aTopRadius,
+                                                           aHeight));
+
+  // These checks should be made to the GUI for the feature but
+  // the corresponding validator does not exist yet.
+  if (!aConeAlgo->check()) {
+    setError(aConeAlgo->getError());
+    return;
+  }
+
+  // Build the sphere
+  aConeAlgo->build();
+
+  // Check if the creation of the cylinder
+  if(!aConeAlgo->isDone()) {
+    setError(aConeAlgo->getError());
+    return;
+  }
+  if(!aConeAlgo->checkValid("Cone builder")) {
+    setError(aConeAlgo->getError());
+    return;
+  }
+
+  int aResultIndex = 0;
+  ResultBodyPtr aResultBox = document()->createBody(data(), aResultIndex);
+  loadNamingDS(aConeAlgo, aResultBox);
+  setResult(aResultBox, aResultIndex);
+}
+
+//=================================================================================================
+void PrimitivesPlugin_Cone::loadNamingDS(std::shared_ptr<GeomAlgoAPI_Cone> theConeAlgo,
+                                         std::shared_ptr<ModelAPI_ResultBody> theResultCone)
+{
+  // Load the result
+  theResultCone->store(theConeAlgo->shape());
+
+  // Prepare the naming
+  theConeAlgo->prepareNamingFaces();
+
+  // Insert to faces
+  int num = 1;
+  std::map< std::string, std::shared_ptr<GeomAPI_Shape> > listOfFaces =
+      theConeAlgo->getCreatedFaces();
+  int nbFaces = 0;
+  for (std::map< std::string, std::shared_ptr<GeomAPI_Shape> >::iterator
+       it=listOfFaces.begin(); it!=listOfFaces.end(); ++it) {
+    std::shared_ptr<GeomAPI_Shape> aFace = (*it).second;
+    theResultCone->generated(aFace, (*it).first, num++);
+    nbFaces++;
+  }
+
+  if (nbFaces == 2) {
+    // Naming vertices
+    GeomAPI_DataMapOfShapeShape aVertices;
+    GeomAPI_ShapeExplorer aVertExp(theConeAlgo->shape(), GeomAPI_Shape::VERTEX);
+    for(int anIndex = 1; aVertExp.more(); aVertExp.next()) {
+      if (!aVertices.isBound(aVertExp.current())) {
+        std::ostringstream aStream;
+        aStream<<"Vertex_"<<anIndex++;
+        theResultCone->generated(aVertExp.current(), aStream.str(), num++);
+        aVertices.bind(aVertExp.current(), aVertExp.current());
+      }
+    }
+  }
+}
diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Cone.h b/src/PrimitivesPlugin/PrimitivesPlugin_Cone.h
new file mode 100644 (file)
index 0000000..9cbc0b1
--- /dev/null
@@ -0,0 +1,88 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D
+
+// File:        PrimitivesPlugin_Cone.h
+// Created:     17 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#ifndef PRIMITIVESPLUGIN_CONE_H_
+#define PRIMITIVESPLUGIN_CONE_H_
+
+#include <PrimitivesPlugin.h>
+#include <ModelAPI_Feature.h>
+#include <GeomAlgoAPI_Cone.h>
+
+/**\class PrimitivesPlugin_Cone
+ * \ingroup Plugins
+ * \brief Feature for creation of a cone.
+ *
+ * Creates a cone from a 
+ */
+class PrimitivesPlugin_Cone : public ModelAPI_Feature
+{
+ public:
+  /// Cone kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_CONE_ID("Cone");
+    return MY_CONE_ID;
+  }
+
+  /// Attribute name of the base point
+  inline static const std::string& BASE_POINT_ID()
+  {
+    static const std::string MY_BASE_POINT_ID("base_point");
+    return MY_BASE_POINT_ID;
+  }
+
+  /// Attribute name of the axis
+  inline static const std::string& AXIS_ID()
+  {
+    static const std::string MY_AXIS_ID("axis");
+    return MY_AXIS_ID;
+  }
+
+  /// Attribute name of the base radius
+  inline static const std::string& BASE_RADIUS_ID()
+  {
+    static const std::string MY_BASE_RADIUS_ID("base_radius");
+    return MY_BASE_RADIUS_ID;
+  }
+
+  /// Attribute name of the radius
+  inline static const std::string& TOP_RADIUS_ID()
+  {
+    static const std::string MY_TOP_RADIUS_ID("top_radius");
+    return MY_TOP_RADIUS_ID;
+  }
+
+  /// Attribute name of the radius
+  inline static const std::string& HEIGHT_ID()
+  {
+    static const std::string MY_HEIGHT_ID("height");
+    return MY_HEIGHT_ID;
+  }
+
+  /// Returns the kind of a feature
+  PRIMITIVESPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = PrimitivesPlugin_Cone::ID();
+    return MY_KIND;
+  }
+
+  /// Creates a new part document if needed
+  PRIMITIVESPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  PRIMITIVESPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Use plugin manager for features creation
+  PrimitivesPlugin_Cone();
+
+ private:
+  /// Load Naming data structure of the feature to the document
+  void loadNamingDS(std::shared_ptr<GeomAlgoAPI_Cone> theConeAlgo,
+                    std::shared_ptr<ModelAPI_ResultBody> theResultCone);
+
+};
+
+#endif // PRIMITIVESPLUGIN_CONE_H_
index 9be9781b9cf77ffa95b694e26852c249620895c0..c3d5b82235327c599349018d31b12fb1d094574f 100644 (file)
@@ -33,8 +33,6 @@
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Session.h>
 
-#include <iostream>
-
 //=================================================================================================
 PrimitivesPlugin_Cylinder::PrimitivesPlugin_Cylinder()
 {
index 1e46c9b0a8ba2d7f295c1653b2af32420e83ef87..f190df93edac29db58a8ecad3b7fcbdc97721547 100644 (file)
 #include <PrimitivesPlugin_Plugin.h>
 
 #include <PrimitivesPlugin_Box.h>
+#include <PrimitivesPlugin_Cone.h>
 #include <PrimitivesPlugin_Cylinder.h>
+#include <PrimitivesPlugin_Sphere.h>
+#include <PrimitivesPlugin_Torus.h>
+
 #include <ModelAPI_Session.h>
 
 #include <string>
@@ -41,8 +45,14 @@ FeaturePtr PrimitivesPlugin_Plugin::createFeature(std::string theFeatureID)
 {
   if (theFeatureID == PrimitivesPlugin_Box::ID()) {
     return FeaturePtr(new PrimitivesPlugin_Box);
+  } else if (theFeatureID == PrimitivesPlugin_Cone::ID()) {
+    return FeaturePtr(new PrimitivesPlugin_Cone);
   } else if (theFeatureID == PrimitivesPlugin_Cylinder::ID()) {
     return FeaturePtr(new PrimitivesPlugin_Cylinder);
+  } else if (theFeatureID == PrimitivesPlugin_Sphere::ID()) {
+    return FeaturePtr(new PrimitivesPlugin_Sphere);
+  } else if (theFeatureID == PrimitivesPlugin_Torus::ID()) {
+    return FeaturePtr(new PrimitivesPlugin_Torus);
   }
   // feature of such kind is not found
   return FeaturePtr();
diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.cpp b/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.cpp
new file mode 100644 (file)
index 0000000..c01d2b2
--- /dev/null
@@ -0,0 +1,129 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D
+
+// File:        PrimitivesPlugin_Sphere.h
+// Created:     15 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#include <PrimitivesPlugin_Sphere.h>
+
+#include <GeomAPI_ShapeExplorer.h>
+
+#include <GeomAlgoAPI_PointBuilder.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+
+#include <sstream>
+
+//=================================================================================================
+PrimitivesPlugin_Sphere::PrimitivesPlugin_Sphere()
+{
+}
+
+//=================================================================================================
+void PrimitivesPlugin_Sphere::initAttributes()
+{
+  data()->addAttribute(PrimitivesPlugin_Sphere::CENTER_POINT_ID(),
+                       ModelAPI_AttributeSelection::typeId());
+
+  data()->addAttribute(PrimitivesPlugin_Sphere::RADIUS_ID(),
+                       ModelAPI_AttributeDouble::typeId());
+
+  // Initialize the center point of the sphere at the origin if the center point is not filled.
+  AttributeSelectionPtr aCenterPoint =
+    data()->selection(PrimitivesPlugin_Sphere::CENTER_POINT_ID());
+  if (!aCenterPoint->isInitialized()) {
+    ObjectPtr aPointObj = ModelAPI_Session::get()->moduleDocument()
+      ->objectByName(ModelAPI_ResultConstruction::group(), "Origin");
+    if (aPointObj.get()) {
+      ResultPtr aPointRes = std::dynamic_pointer_cast<ModelAPI_Result>(aPointObj);
+      aCenterPoint->setValue(aPointRes, std::shared_ptr<GeomAPI_Shape>());
+    }
+  }
+}
+
+//=================================================================================================
+void PrimitivesPlugin_Sphere::execute()
+{
+  // Getting point.
+  std::shared_ptr<GeomAPI_Pnt> aCenterPoint;
+  std::shared_ptr<ModelAPI_AttributeSelection> aPointRef =
+    selection(PrimitivesPlugin_Sphere::CENTER_POINT_ID());
+  if (aPointRef.get() != NULL) {
+    GeomShapePtr aShape1 = aPointRef->value();
+    if (!aShape1.get()) {
+      aShape1 = aPointRef->context()->shape();
+    }
+    if (aShape1) {
+       aCenterPoint = GeomAlgoAPI_PointBuilder::point(aShape1);
+    }
+  }
+
+  // Getting radius
+  double aRadius = real(PrimitivesPlugin_Sphere::RADIUS_ID())->value();
+
+  std::shared_ptr<GeomAlgoAPI_Sphere> aSphereAlgo =
+    std::shared_ptr<GeomAlgoAPI_Sphere>(new GeomAlgoAPI_Sphere(aCenterPoint, aRadius));
+
+  // These checks should be made to the GUI for the feature but
+  // the corresponding validator does not exist yet.
+  if (!aSphereAlgo->check()) {
+    setError(aSphereAlgo->getError());
+    return;
+  }
+
+  // Build the sphere
+  aSphereAlgo->build();
+
+  // Check if the creation of the cylinder
+  if(!aSphereAlgo->isDone()) {
+    setError(aSphereAlgo->getError());
+    return;
+  }
+  if(!aSphereAlgo->checkValid("Sphere builder")) {
+    setError(aSphereAlgo->getError());
+    return;
+  }
+
+  int aResultIndex = 0;
+  ResultBodyPtr aResultBox = document()->createBody(data(), aResultIndex);
+  loadNamingDS(aSphereAlgo, aResultBox);
+  setResult(aResultBox, aResultIndex);
+}
+
+//=================================================================================================
+void PrimitivesPlugin_Sphere::loadNamingDS(std::shared_ptr<GeomAlgoAPI_Sphere> theSphereAlgo,
+                                           std::shared_ptr<ModelAPI_ResultBody> theResultSphere)
+{
+  // Load the result
+  theResultSphere->store(theSphereAlgo->shape());
+
+  // Prepare the naming
+  theSphereAlgo->prepareNamingFaces();
+
+  // Insert to faces
+  // Naming for faces and edges
+  int num = 1;
+  std::map< std::string, std::shared_ptr<GeomAPI_Shape> > listOfFaces =
+      theSphereAlgo->getCreatedFaces();
+  for (std::map< std::string, std::shared_ptr<GeomAPI_Shape> >::iterator
+       it=listOfFaces.begin(); it!=listOfFaces.end(); ++it) {
+    std::shared_ptr<GeomAPI_Shape> aFace = (*it).second;
+    theResultSphere->generated(aFace, (*it).first, num++);
+  }
+
+  // Naming vertices
+  GeomAPI_DataMapOfShapeShape aVertices;
+  GeomAPI_ShapeExplorer aVertExp(theSphereAlgo->shape(), GeomAPI_Shape::VERTEX);
+  for(int anIndex = 1; aVertExp.more(); aVertExp.next()) {
+    if (!aVertices.isBound(aVertExp.current())) {
+      std::ostringstream aStream;
+      aStream<<"Vertex_"<<anIndex++;
+      theResultSphere->generated(aVertExp.current(), aStream.str(), num++);
+      aVertices.bind(aVertExp.current(), aVertExp.current());
+    }
+  }
+}
diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.h b/src/PrimitivesPlugin/PrimitivesPlugin_Sphere.h
new file mode 100644 (file)
index 0000000..08693f3
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D
+
+// File:        PrimitivesPlugin_Sphere.h
+// Created:     15 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#ifndef PRIMITIVESPLUGIN_SPHERE_H_
+#define PRIMITIVESPLUGIN_SPHERE_H_
+
+#include <PrimitivesPlugin.h>
+#include <ModelAPI_Feature.h>
+#include <GeomAlgoAPI_Sphere.h>
+
+/**\class PrimitivesPlugin_Sphere
+ * \ingroup Plugins
+ * \brief Feature for creation of a sphere.
+ *
+ * Creates a sphere from a radius and a center point defaulting to the origin
+ */
+class PrimitivesPlugin_Sphere : public ModelAPI_Feature
+{
+ public:
+  /// Sphere kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_SPHERE_ID("Sphere");
+    return MY_SPHERE_ID;
+  }
+
+  /// Attribute name of the base point
+  inline static const std::string& CENTER_POINT_ID()
+  {
+    static const std::string MY_CENTER_POINT_ID("center_point");
+    return MY_CENTER_POINT_ID;
+  }
+
+  /// Attribute name of the radius
+  inline static const std::string& RADIUS_ID()
+  {
+    static const std::string MY_RADIUS_ID("radius");
+    return MY_RADIUS_ID;
+  }
+
+  /// Returns the kind of a feature
+  PRIMITIVESPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = PrimitivesPlugin_Sphere::ID();
+    return MY_KIND;
+  }
+
+  /// Creates a new part document if needed
+  PRIMITIVESPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  PRIMITIVESPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Use plugin manager for features creation
+  PrimitivesPlugin_Sphere();
+
+ private:
+  /// Load Naming data structure of the feature to the document
+  void loadNamingDS(std::shared_ptr<GeomAlgoAPI_Sphere> theSphereAlgo,
+                    std::shared_ptr<ModelAPI_ResultBody> theResultSphere);
+
+};
+
+#endif // PRIMITIVESPLUGIN_SPHERE_H_
diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Torus.cpp b/src/PrimitivesPlugin/PrimitivesPlugin_Torus.cpp
new file mode 100644 (file)
index 0000000..a086def
--- /dev/null
@@ -0,0 +1,165 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D
+
+// File:        PrimitivesPlugin_Torus.cpp
+// Created:     17 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#include <PrimitivesPlugin_Torus.h>
+
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Lin.h>
+#include <GeomAPI_ShapeExplorer.h>
+
+#include <GeomAlgoAPI_PointBuilder.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+
+#include <sstream>
+
+//=================================================================================================
+PrimitivesPlugin_Torus::PrimitivesPlugin_Torus()
+{
+}
+
+//=================================================================================================
+void PrimitivesPlugin_Torus::initAttributes()
+{
+  data()->addAttribute(PrimitivesPlugin_Torus::BASE_POINT_ID(),
+                       ModelAPI_AttributeSelection::typeId());
+  data()->addAttribute(PrimitivesPlugin_Torus::AXIS_ID(),
+                       ModelAPI_AttributeSelection::typeId());
+
+  data()->addAttribute(PrimitivesPlugin_Torus::RADIUS_ID(),
+                       ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(PrimitivesPlugin_Torus::RING_RADIUS_ID(),
+                       ModelAPI_AttributeDouble::typeId());
+
+  // Initialize the base point of the torus at the origin if the base point is not filled.
+  AttributeSelectionPtr aCenterPoint =
+    data()->selection(PrimitivesPlugin_Torus::BASE_POINT_ID());
+  if (!aCenterPoint->isInitialized()) {
+    ObjectPtr aPointObj = ModelAPI_Session::get()->moduleDocument()
+      ->objectByName(ModelAPI_ResultConstruction::group(), "Origin");
+    if (aPointObj.get()) {
+      ResultPtr aPointRes = std::dynamic_pointer_cast<ModelAPI_Result>(aPointObj);
+      aCenterPoint->setValue(aPointRes, std::shared_ptr<GeomAPI_Shape>());
+    }
+  }
+
+  // Initialize the axis at the OZ axis if the axis is not filled.
+  AttributeSelectionPtr anAxis = data()->selection(PrimitivesPlugin_Torus::AXIS_ID());
+  if (!anAxis->isInitialized()) {
+    ObjectPtr anAxisObj = ModelAPI_Session::get()->moduleDocument()
+      ->objectByName(ModelAPI_ResultConstruction::group(), "OZ");
+    if (anAxisObj.get()) {
+      ResultPtr anAxisRes = std::dynamic_pointer_cast<ModelAPI_Result>(anAxisObj);
+      anAxis->setValue(anAxisRes, std::shared_ptr<GeomAPI_Shape>());
+    }
+  }
+}
+
+//=================================================================================================
+void PrimitivesPlugin_Torus::execute()
+{
+  // Getting base point.
+  std::shared_ptr<GeomAPI_Pnt> aBasePoint;
+  std::shared_ptr<ModelAPI_AttributeSelection> aPointRef =
+    selection(PrimitivesPlugin_Torus::BASE_POINT_ID());
+  if (aPointRef.get() != NULL) {
+    GeomShapePtr aShape1 = aPointRef->value();
+    if (!aShape1.get()) {
+      aShape1 = aPointRef->context()->shape();
+    }
+    if (aShape1) {
+       aBasePoint = GeomAlgoAPI_PointBuilder::point(aShape1);
+    }
+  }
+
+  // Getting axis.
+  std::shared_ptr<GeomAPI_Ax2> anAxis;
+  std::shared_ptr<GeomAPI_Edge> anEdge;
+  std::shared_ptr<ModelAPI_AttributeSelection> anEdgeRef =
+    selection(PrimitivesPlugin_Torus::AXIS_ID());
+  if(anEdgeRef && anEdgeRef->value() && anEdgeRef->value()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anEdgeRef->value()));
+  } else if (anEdgeRef && !anEdgeRef->value() && anEdgeRef->context() &&
+             anEdgeRef->context()->shape() && anEdgeRef->context()->shape()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anEdgeRef->context()->shape()));
+  }
+  if(anEdge) {
+    anAxis = std::shared_ptr<GeomAPI_Ax2>(new GeomAPI_Ax2(aBasePoint,
+                                                          anEdge->line()->direction()));
+  }
+
+  // Getting radius and ring radius
+  double aRadius = real(PrimitivesPlugin_Torus::RADIUS_ID())->value();
+  double aRingRadius = real(PrimitivesPlugin_Torus::RING_RADIUS_ID())->value();
+
+  std::shared_ptr<GeomAlgoAPI_Torus> aTorusAlgo =
+    std::shared_ptr<GeomAlgoAPI_Torus>(new GeomAlgoAPI_Torus(anAxis,
+                                                             aRadius,
+                                                             aRingRadius));
+
+  // These checks should be made to the GUI for the feature but
+  // the corresponding validator does not exist yet.
+  if (!aTorusAlgo->check()) {
+    setError(aTorusAlgo->getError());
+    return;
+  }
+
+  // Build the sphere
+  aTorusAlgo->build();
+
+  // Check if the creation of the cylinder
+  if(!aTorusAlgo->isDone()) {
+    setError(aTorusAlgo->getError());
+    return;
+  }
+  if(!aTorusAlgo->checkValid("Torus builder")) {
+    setError(aTorusAlgo->getError());
+    return;
+  }
+
+  int aResultIndex = 0;
+  ResultBodyPtr aResultBox = document()->createBody(data(), aResultIndex);
+  loadNamingDS(aTorusAlgo, aResultBox);
+  setResult(aResultBox, aResultIndex);
+}
+
+//=================================================================================================
+void PrimitivesPlugin_Torus::loadNamingDS(std::shared_ptr<GeomAlgoAPI_Torus> theTorusAlgo,
+                                          std::shared_ptr<ModelAPI_ResultBody> theResultTorus)
+{
+  // Load the result
+  theResultTorus->store(theTorusAlgo->shape());
+
+  // Prepare the naming
+  theTorusAlgo->prepareNamingFaces();
+
+  // Insert to faces
+  // Naming for faces
+  int num = 1;
+  std::map< std::string, std::shared_ptr<GeomAPI_Shape> > listOfFaces =
+      theTorusAlgo->getCreatedFaces();
+  for (std::map< std::string, std::shared_ptr<GeomAPI_Shape> >::iterator
+       it=listOfFaces.begin(); it!=listOfFaces.end(); ++it) {
+    std::shared_ptr<GeomAPI_Shape> aFace = (*it).second;
+    theResultTorus->generated(aFace, (*it).first, num++);
+  }
+
+  // Naming of edges
+  GeomAPI_DataMapOfShapeShape anEdges;
+  GeomAPI_ShapeExplorer anEdgeExp(theTorusAlgo->shape(), GeomAPI_Shape::EDGE);
+  for(int anIndex = 1; anEdgeExp.more(); anEdgeExp.next()) {
+    if (!anEdges.isBound(anEdgeExp.current())) {
+      std::ostringstream aStream;
+      aStream<<"Edge_"<<anIndex++;
+      theResultTorus->generated(anEdgeExp.current(), aStream.str(), num++);
+      anEdges.bind(anEdgeExp.current(), anEdgeExp.current());
+    }
+  }
+}
diff --git a/src/PrimitivesPlugin/PrimitivesPlugin_Torus.h b/src/PrimitivesPlugin/PrimitivesPlugin_Torus.h
new file mode 100644 (file)
index 0000000..69ea8bf
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright (C) 2014-201x CEA/DEN, EDF R&D
+
+// File:        PrimitivesPlugin_Torus.h
+// Created:     17 Mar 2017
+// Author:      Clarisse Genrault (CEA)
+
+#ifndef PRIMITIVESPLUGIN_TORUS_H_
+#define PRIMITIVESPLUGIN_TORUS_H_
+
+#include <PrimitivesPlugin.h>
+#include <ModelAPI_Feature.h>
+#include <GeomAlgoAPI_Torus.h>
+
+/**\class PrimitivesPlugin_Torus
+ * \ingroup Plugins
+ * \brief Feature for creation of a torus.
+ *
+ * Creates a torus from a 
+ */
+class PrimitivesPlugin_Torus : public ModelAPI_Feature
+{
+ public:
+  /// Torus kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_TORUS_ID("Torus");
+    return MY_TORUS_ID;
+  }
+
+  /// Attribute name of the base point
+  inline static const std::string& BASE_POINT_ID()
+  {
+    static const std::string MY_BASE_POINT_ID("base_point");
+    return MY_BASE_POINT_ID;
+  }
+
+  /// Attribute name of the axis
+  inline static const std::string& AXIS_ID()
+  {
+    static const std::string MY_AXIS_ID("axis");
+    return MY_AXIS_ID;
+  }
+
+  /// Attribute name of the radius
+  inline static const std::string& RADIUS_ID()
+  {
+    static const std::string MY_RADIUS_ID("radius");
+    return MY_RADIUS_ID;
+  }
+
+  /// Attribute name of the section radius
+  inline static const std::string& RING_RADIUS_ID()
+  {
+    static const std::string MY_RING_RADIUS_ID("ring_radius");
+    return MY_RING_RADIUS_ID;
+  }
+
+  /// Returns the kind of a feature
+  PRIMITIVESPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = PrimitivesPlugin_Torus::ID();
+    return MY_KIND;
+  }
+
+  /// Creates a new part document if needed
+  PRIMITIVESPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  PRIMITIVESPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Use plugin manager for features creation
+  PrimitivesPlugin_Torus();
+
+ private:
+  /// Load Naming data structure of the feature to the document
+  void loadNamingDS(std::shared_ptr<GeomAlgoAPI_Torus> theTorusAlgo,
+                    std::shared_ptr<ModelAPI_ResultBody> theResultTorus);
+
+};
+
+#endif // PRIMITIVESPLUGIN_TORUS_H_
diff --git a/src/PrimitivesPlugin/cone_widget.xml b/src/PrimitivesPlugin/cone_widget.xml
new file mode 100644 (file)
index 0000000..4f1acd5
--- /dev/null
@@ -0,0 +1,46 @@
+<!-- Copyright (C) 2014-201x CEA/DEN, EDF R&D -->
+
+<source>
+  <shape_selector
+      id="base_point"
+      label="base_point"
+      default=""
+      shape_types="vertex"
+      icon="icons/Primitives/point.png"
+      tooltip="Select the center of the base of the cone">
+    <validator id="GeomValidators_ConstructionComposite"/>
+    <validator id="GeomValidators_ShapeType" parameters="vertex"/>
+  </shape_selector>
+  <shape_selector
+      id="axis"
+      label="axis"
+      default=""
+      shape_types="edge"
+      icon="icons/Primitives/axis.png"
+      tooltip="Select the axis of the cone">
+    <validator id="GeomValidators_ConstructionComposite"/>
+    <validator id="GeomValidators_ShapeType" parameters="line"/>
+  </shape_selector>
+  <doublevalue
+    id="base_radius"
+    label="Base radius"
+    step="1."
+    default="10."
+    tooltip="Enter the base radius of the cone">
+  </doublevalue>
+  <doublevalue
+    id="top_radius"
+    label="Top radius"
+    step="1."
+    default="5."
+    tooltip="Enter the top radius of the cone">
+  </doublevalue>
+  <doublevalue
+    id="height"
+    label="height"
+    step="1."
+    default="10."
+    icon="icons/Primitives/dimension_v.png"
+    tooltip="Enter the height of the cone">
+  </doublevalue>
+</source>
\ No newline at end of file
diff --git a/src/PrimitivesPlugin/icons/SVG/cone.svg b/src/PrimitivesPlugin/icons/SVG/cone.svg
new file mode 100644 (file)
index 0000000..bcf82d6
--- /dev/null
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="16"
+   height="16"
+   id="svg4157"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   viewBox="0 0 16 16"
+   sodipodi:docname="cone.svg"
+   inkscape:export-filename="/export/home/ldigallo/DOC_ALYOTECH/icones/Primitives/cone.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs4159" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="44.791208"
+     inkscape:cx="10.619534"
+     inkscape:cy="7.8334642"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     showguides="true"
+     inkscape:snap-others="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-object-midpoints="false"
+     inkscape:snap-center="true"
+     inkscape:snap-text-baseline="false"
+     inkscape:object-nodes="true"
+     inkscape:snap-smooth-nodes="true"
+     inkscape:snap-intersection-paths="true"
+     inkscape:snap-page="false"
+     inkscape:snap-grids="false"
+     inkscape:object-paths="true"
+     inkscape:window-width="1920"
+     inkscape:window-height="1006"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="1"
+     inkscape:showpageshadow="false">
+    <inkscape:grid
+       type="xygrid"
+       id="grid4705" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata4162">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     transform="translate(0,-16)">
+    <g
+       id="g4140"
+       transform="matrix(0.48922312,0,0,0.49910601,0.29944485,16.003478)">
+      <ellipse
+         ry="2.0393512"
+         rx="3.7681725"
+         cy="4.1903658"
+         cx="15.684584"
+         id="path4707"
+         style="fill:#000000;fill-opacity:1;stroke:#1b4955;stroke-width:4.19104528;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <path
+         sodipodi:open="true"
+         d="m 27.924641,24.480045 a 12.381138,4.5885401 0 0 1 -5.389494,4.630461 12.381138,4.5885401 0 0 1 -13.6070929,0 12.381138,4.5885401 0 0 1 -5.3894938,-4.630461"
+         sodipodi:end="3.3161256"
+         sodipodi:start="6.1086524"
+         sodipodi:ry="4.5885401"
+         sodipodi:rx="12.381138"
+         sodipodi:cy="25.276836"
+         sodipodi:cx="15.731601"
+         sodipodi:type="arc"
+         id="path4713"
+         style="fill:none;fill-opacity:1;stroke:#1b4955;stroke-width:4.19104528;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path4786"
+         d="M 11.916411,4.190366 3.5058978,24.55204"
+         style="fill:none;fill-rule:evenodd;stroke:#1b4955;stroke-width:4.19099998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path4788"
+         d="m 19.452756,4.190366 8.523265,20.406455"
+         style="fill:none;fill-rule:evenodd;stroke:#1b4955;stroke-width:4.19104528;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path4792"
+         d="M 14.290381,28.788695 C 10.180956,28.613169 6.4375964,27.579732 5.0085088,26.226233 4.6609485,25.897057 4.4594815,25.552368 4.4594815,25.286905 c 0,-0.138879 0.9795392,-2.55794 3.8491936,-9.505936 2.1170569,-5.125808 3.8663729,-9.3363317 3.8873699,-9.356719 0.021,-0.020387 0.142544,0.025619 0.270103,0.1022359 0.127559,0.076617 0.427949,0.2108717 0.667533,0.2983439 0.917499,0.3349788 1.766737,0.459885 2.862003,0.4209446 1.069767,-0.038034 1.89748,-0.229734 2.734381,-0.6332892 0.250542,-0.1208116 0.45974,-0.2144914 0.464884,-0.2081775 0.0052,0.00631 1.764658,4.2160153 3.910029,9.3548903 2.91379,6.979495 3.900674,9.39029 3.900674,9.528701 0,0.578492 -0.809317,1.319189 -2.086026,1.909156 -1.978433,0.914234 -4.683823,1.458828 -7.928702,1.596046 -1.178869,0.04985 -1.440285,0.04942 -2.700543,-0.0044 l 0,-3e-6 z"
+         style="fill:#b7d9ea;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <ellipse
+         ry="1.8799957"
+         rx="3.5278082"
+         cy="3.3025274"
+         cx="15.636511"
+         id="path4707-9"
+         style="fill:#b7d9ea;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    </g>
+  </g>
+</svg>
diff --git a/src/PrimitivesPlugin/icons/SVG/torus.svg b/src/PrimitivesPlugin/icons/SVG/torus.svg
new file mode 100644 (file)
index 0000000..1f4e436
--- /dev/null
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="16"
+   height="16"
+   id="svg4700"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   viewBox="0 0 16 16"
+   sodipodi:docname="torus.svg"
+   inkscape:export-filename="/export/home/ldigallo/DOC_ALYOTECH/icones/Primitives/torus.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs4702">
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker4450"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4452"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker4434"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4436"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lstart"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4170"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="42.71875"
+     inkscape:cx="7.4081323"
+     inkscape:cy="8.3624015"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     showguides="true"
+     inkscape:snap-object-midpoints="false"
+     inkscape:snap-center="true"
+     inkscape:window-width="1920"
+     inkscape:window-height="1006"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="1"
+     inkscape:snap-others="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-grids="false"
+     inkscape:showpageshadow="false"
+     showborder="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid5248" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata4705">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     transform="translate(0,-16)">
+    <g
+       id="g4179"
+       transform="matrix(1,0,0,1.1022834,-0.04681784,-2.5396163)">
+      <ellipse
+         ry="2.1029613"
+         rx="2.5721776"
+         cy="24.088104"
+         cx="8.0245848"
+         id="path5250"
+         style="fill:none;fill-opacity:1;stroke:#1b4955;stroke-width:2.28365493;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <ellipse
+         ry="5.5472407"
+         rx="6.7849512"
+         cy="24.088104"
+         cx="8.0245848"
+         id="path5250-7"
+         style="opacity:1;fill:none;fill-opacity:1;stroke:#1b4955;stroke-width:2.28365493;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path4163"
+         d="M 7.3830656,28.970613 C 6.9591888,28.93369 6.5847252,28.865163 6.1216233,28.739766 3.939623,28.148936 2.3343232,26.553308 2.0542907,24.69694 c -0.059727,-0.395941 -0.026579,-1.199534 0.06393,-1.549817 0.2441973,-0.945074 0.7282812,-1.715403 1.5083369,-2.400239 1.0414383,-0.914309 2.439622,-1.460679 3.968098,-1.550617 2.6285644,-0.154668 5.0553554,1.09409 6.0316174,3.103697 0.249677,0.513954 0.374766,1.022658 0.401375,1.632277 0.129471,2.966315 -3.01956,5.354123 -6.6445827,5.038372 z m 1.4750261,-2.21691 c 0.5665465,-0.119025 1.0649768,-0.349607 1.5010603,-0.694414 1.344125,-1.062792 1.365432,-2.81722 0.04742,-3.904876 -0.4423445,-0.365035 -0.933834,-0.599155 -1.5404683,-0.7338 -0.3675822,-0.08159 -1.0965106,-0.10042 -1.4681193,-0.03793 -0.6943238,0.116752 -1.2018962,0.334626 -1.7037842,0.731346 -0.4370814,0.345495 -0.7235718,0.734014 -0.9039922,1.225935 -0.083643,0.228056 -0.091134,0.286581 -0.093426,0.730023 -0.00271,0.522574 0.017695,0.620916 0.2185705,1.053794 0.3591292,0.77391 1.2591819,1.416179 2.2924167,1.635845 0.5068234,0.107752 1.1197254,0.105554 1.6503207,-0.0059 z"
+         style="opacity:1;fill:#b7d9ea;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    </g>
+  </g>
+</svg>
diff --git a/src/PrimitivesPlugin/icons/cone.png b/src/PrimitivesPlugin/icons/cone.png
new file mode 100644 (file)
index 0000000..4c89e62
Binary files /dev/null and b/src/PrimitivesPlugin/icons/cone.png differ
diff --git a/src/PrimitivesPlugin/icons/sphere.png b/src/PrimitivesPlugin/icons/sphere.png
new file mode 100644 (file)
index 0000000..000d658
Binary files /dev/null and b/src/PrimitivesPlugin/icons/sphere.png differ
diff --git a/src/PrimitivesPlugin/icons/torus.png b/src/PrimitivesPlugin/icons/torus.png
new file mode 100644 (file)
index 0000000..254cd0a
Binary files /dev/null and b/src/PrimitivesPlugin/icons/torus.png differ
index 4a4b98403ae8ea2991c6f8a5e1864c3b60d86610..ab969f15d9c77df7732a85513ff24c6a91c64ed2 100644 (file)
@@ -31,5 +31,20 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
         <source path="cylinder_widget.xml"/>
       </feature>
     </group>
+    <group id="Primitives">
+      <feature id="Sphere" title="Sphere" tooltip="Create a sphere" icon="icons/Primitives/sphere.png">
+        <source path="sphere_widget.xml"/>
+      </feature>
+    </group>
+    <group id="Primitives">
+      <feature id="Torus" title="Torus" tooltip="Create a Torus" icon="icons/Primitives/torus.png">
+        <source path="torus_widget.xml"/>
+      </feature>
+    </group>
+    <group id="Primitives">
+      <feature id="Cone" title="Cone" tooltip="Create a Cone" icon="icons/Primitives/cone.png">
+        <source path="cone_widget.xml"/>
+      </feature>
+    </group>
   </workbench>
 </plugin>
diff --git a/src/PrimitivesPlugin/sphere_widget.xml b/src/PrimitivesPlugin/sphere_widget.xml
new file mode 100644 (file)
index 0000000..664f41a
--- /dev/null
@@ -0,0 +1,17 @@
+<!-- Copyright (C) 2014-201x CEA/DEN, EDF R&D -->
+
+<source>
+  <shape_selector id="center_point"
+                  label="Center point"
+                  icon="icons/Primitives/point.png"
+                  tooltip="Select a center point"
+                  shape_types="vertex">
+  </shape_selector>
+  <doublevalue id="radius"
+               label="Radius"
+               icon="icons/Primitives/radius.png"
+               tooltip="Enter a radius"
+               step="1."
+               default="10.">
+  </doublevalue>
+</source>
\ No newline at end of file
diff --git a/src/PrimitivesPlugin/torus_widget.xml b/src/PrimitivesPlugin/torus_widget.xml
new file mode 100644 (file)
index 0000000..44d0ce6
--- /dev/null
@@ -0,0 +1,38 @@
+<!-- Copyright (C) 2014-201x CEA/DEN, EDF R&D -->
+
+<source>
+  <shape_selector
+      id="base_point"
+      label="base_point"
+      default=""
+      shape_types="vertex"
+      icon="icons/Primitives/point.png"
+      tooltip="Select the center of the torus">
+    <validator id="GeomValidators_ConstructionComposite"/>
+    <validator id="GeomValidators_ShapeType" parameters="vertex"/>
+  </shape_selector>
+  <shape_selector
+      id="axis"
+      label="axis"
+      default=""
+      shape_types="edge"
+      icon="icons/Primitives/axis.png"
+      tooltip="Select the axis of the torus">
+    <validator id="GeomValidators_ConstructionComposite"/>
+    <validator id="GeomValidators_ShapeType" parameters="line"/>
+  </shape_selector>
+  <doublevalue
+    id="radius"
+    label="Radius"
+    step="1."
+    default="15."
+    tooltip="Enter the radius of the torus">
+  </doublevalue>
+  <doublevalue
+    id="ring_radius"
+    label="Ring radius"
+    step="1."
+    default="3."
+    tooltip="Enter the ring radius of the torus">
+  </doublevalue>
+</source>
\ No newline at end of file
index 7f678f5d320c38385036816822868868109f3fef..a69fea2d010d28f9cb992ecfdaef9b1f10b2e4c9 100644 (file)
@@ -2,7 +2,7 @@
 """
 
 from FeaturesAPI import addPlacement, addRotation, addScale, addSymmetry, addTranslation
-from FeaturesAPI import addMultiTranslation
+from FeaturesAPI import addMultiTranslation, addMultiRotation
 from FeaturesAPI import addExtrusion, addExtrusionCut, addExtrusionFuse
 from FeaturesAPI import addRevolution, addRevolutionCut, addRevolutionFuse
 from FeaturesAPI import addPipe
index 49d9adb32d9ef049dae12a859c730bd050130bff..a707b9cfe838c0a5dfa011fb07adea1e62adaa4a 100644 (file)
@@ -1,4 +1,4 @@
 """Package for Primitives plugin for the Parametric Geometry API of the Modeler.
 """
 
-from PrimitivesAPI import addBox, addCylinder
+from PrimitivesAPI import addBox, addCone, addCylinder, addSphere, addTorus
index e2f8246554d1f9dd9f01336222c75af6c7c68698..746b33e03ec1f2b8a4530c33cb27996a186c01cf 100644 (file)
@@ -130,9 +130,13 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
         // Check that new folders could appear
         QStringList aNotEmptyFolders = listOfShowNotEmptyFolders();
         foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
-          if ((aNotEmptyFolder.toStdString() == aObjType) && (aRootDoc->size(aObjType) == 1))
+          if ((aNotEmptyFolder.toStdString() == aObjType) && (aRootDoc->size(aObjType) > 0)) {
             // Appears first object in folder which can not be shown empty
-            insertRow(myXMLReader->rootFolderId(aObjType));
+            if (!hasShownFolder(aRootDoc, aNotEmptyFolder)) {
+              insertRow(myXMLReader->rootFolderId(aObjType));
+              addShownFolder(aRootDoc, aNotEmptyFolder);
+            }
+          }
         }
         // Insert new object
         int aRow = aRootDoc->size(aObjType) - 1;
@@ -153,10 +157,14 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
           // Check that new folders could appear
           QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false);
           foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
-            if ((aNotEmptyFolder.toStdString() == aObjType) && (aDoc->size(aObjType) == 1))
+            if ((aNotEmptyFolder.toStdString() == aObjType) && (aDoc->size(aObjType) > 0)) {
               // Appears first object in folder which can not be shown empty
-              insertRow(myXMLReader->subFolderId(aObjType), aDocRoot);
-          }
+              if (!hasShownFolder(aDoc, aNotEmptyFolder)) {
+                insertRow(myXMLReader->subFolderId(aObjType), aDocRoot);
+                addShownFolder(aDoc, aNotEmptyFolder);
+              }
+            }
+         }
           int aRow = aDoc->index(aObject);
           if (aRow != -1) {
             int aNbSubFolders = foldersCount(aDoc.get());
@@ -227,6 +235,7 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
           if ((aNotEmptyFolder.toStdString() == aGroup) && (aRootDoc->size(aGroup) == 0)) {
             // Appears first object in folder which can not be shown empty
             removeRow(myXMLReader->rootFolderId(aGroup));
+            removeShownFolder(aRootDoc, aNotEmptyFolder);
             //rebuildBranch(0, aNbFolders + aDoc->size(myXMLReader->rootType()));
             break;
           }
@@ -257,6 +266,7 @@ void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMess
             if ((aNotEmptyFolder.toStdString() == aGroup) && (aSize == 0)) {
               // Appears first object in folder which can not be shown empty
               removeRow(myXMLReader->subFolderId(aGroup), aDocRoot);
+              removeShownFolder(aDoc, aNotEmptyFolder);
               //rebuildBranch(0, aNbSubFolders + aDoc->size(myXMLReader->subType()), aDocRoot);
               break;
             }
@@ -392,12 +402,7 @@ QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn
       if (aResult.get()) {
         ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult);
         if (aCompRes.get()) {
-          for (int i = 0; i < aCompRes->numberOfSubs(true); i++) {
-            if (aCompRes->subResult(i, true) == theObject) {
-              aRow = i;
-              break;
-            }
-          }
+          aRow = ModelAPI_Tools::compSolidIndex(aResult);
         }
       }
     }
index cbcb030daf645f294010ebc9c893ed1b9e48fc30..53e9109801667ffbe392733c4636fb5dbbcd619d 100644 (file)
@@ -184,9 +184,34 @@ private:
 
   VisibilityState getVisibilityState(const QModelIndex& theIndex) const;
 
+  void addShownFolder(DocumentPtr theDoc, QString theFolder)
+  {
+    if (!myShownFolders.contains(theDoc)) {
+      myShownFolders[theDoc] = QStringList();
+    }
+    myShownFolders[theDoc].append(theFolder);
+  }
+
+  void removeShownFolder(DocumentPtr theDoc, QString theFolder)
+  {
+    if (myShownFolders.contains(theDoc)) {
+      myShownFolders[theDoc].removeAll(theFolder);
+      if (myShownFolders[theDoc].isEmpty())
+        myShownFolders.remove(theDoc);
+    }
+  }
+
+  bool hasShownFolder(DocumentPtr theDoc, QString theFolder) const
+  {
+    if (myShownFolders.contains(theDoc))
+      return myShownFolders[theDoc].contains(theFolder);
+    return false;
+  }
+
   Config_DataModelReader* myXMLReader;
 
   XGUI_Workshop* myWorkshop;
+  QMap<DocumentPtr, QStringList> myShownFolders;
   //bool myIsEventsProcessingBlocked;
 };
 
index 76ca0417f8e568f0bfca8c6e597e07421234a84c..577685a87a0a792cc83dca533665432292f7e2bf 100755 (executable)
@@ -170,7 +170,7 @@ void XGUI_MenuMgr::createFeatureActions()
         aGroup->featuresInfo();
       std::list<std::shared_ptr<Config_FeatureMessage> >::const_iterator aFIt =
         aFeaturesInfo.begin(), aFLast = aFeaturesInfo.end();
-      int aFSize = aFeaturesInfo.size();
+      size_t aFSize = aFeaturesInfo.size();
       for(int i = 0; aFIt != aFLast; aFIt++, i++) {
         std::shared_ptr<Config_FeatureMessage> aMessage = *aFIt;
         bool aUseSeparator = i == aFSize-1;
index 6abe0d130453c1908454cbc1f94cd3cb715357fa..12a9e1bd6affdfe992e3b9e381f8186b78e9caf2 100644 (file)
@@ -90,6 +90,13 @@ public:
       else if (theEvent->type() == QEvent::KeyPress) {
         QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
         myOperationMgr->setSHIFTPressed(aKeyEvent->modifiers() & Qt::ShiftModifier);
+        switch (aKeyEvent->key()) {
+          case Qt::Key_Escape:
+            isAccepted = myOperationMgr->onKeyPressed(theObject, aKeyEvent);
+          break;
+          default:
+            break;
+        }
       }
     }
     if (!isAccepted)
@@ -104,7 +111,7 @@ private:
 
 XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent,
                                      ModuleBase_IWorkshop* theWorkshop)
-: QObject(theParent), myWorkshop(theWorkshop), mySHIFTPressed(false)
+: QObject(theParent), myWorkshop(theWorkshop), mySHIFTPressed(false), myActiveMessageBox(0)
 {
   /// we need to install filter to the application in order to react to 'Delete' key button
   /// this key can not be a short cut for a corresponded action because we need to set
@@ -628,14 +635,6 @@ bool XGUI_OperationMgr::onKeyReleased(QObject *theObject, QKeyEvent* theEvent)
   ModuleBase_Operation* anOperation = currentOperation();
   bool isAccepted = false;
   switch (theEvent->key()) {
-    case Qt::Key_Escape: {
-      ModuleBase_Operation* aOperation = currentOperation();
-      if (aOperation) {
-        onAbortOperation();
-        isAccepted = true;
-      }
-    }
-    break;
     case Qt::Key_Tab:
     case Qt::Key_Backtab:
     {
@@ -687,6 +686,38 @@ bool XGUI_OperationMgr::onKeyReleased(QObject *theObject, QKeyEvent* theEvent)
   return isAccepted;
 }
 
+bool XGUI_OperationMgr::onKeyPressed(QObject *theObject, QKeyEvent* theEvent)
+{
+  // Let the manager decide what to do with the given key combination.
+  ModuleBase_Operation* anOperation = currentOperation();
+  bool isAccepted = false;
+  switch (theEvent->key()) {
+    case Qt::Key_Escape: {
+      // processing in message box
+      if (myActiveMessageBox)
+      {
+        myActiveMessageBox->reject();
+        isAccepted = true;
+      }
+      // processing in the active widget
+      ModuleBase_Operation* aOperation = currentOperation();
+      if (!isAccepted && aOperation) {
+        ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
+        ModuleBase_ModelWidget* anActiveWgt = aPanel->activeWidget();
+        if (anActiveWgt)
+          isAccepted = anActiveWgt && anActiveWgt->processEscape();
+      }
+      // default Escape button functionality
+      if (!isAccepted && aOperation) {
+        onAbortOperation();
+        isAccepted = true;
+      }
+    }
+    break;
+  }
+  return isAccepted;
+}
+
 bool XGUI_OperationMgr::onProcessEnter(QObject* theObject)
 {
   bool isAccepted = false;
@@ -815,3 +846,14 @@ bool XGUI_OperationMgr::isChildObject(const QObject* theObject, const QObject* t
   }
   return isPPChild;
 }
+
+QMessageBox* XGUI_OperationMgr::createMessageBox(const QString& theMessage)
+{
+  QMessageBox * aMessageBox = new QMessageBox(QMessageBox::Question,
+    QObject::tr("Abort operation"), theMessage, QMessageBox::Ok | QMessageBox::Cancel,
+    qApp->activeWindow());
+  aMessageBox->setDefaultButton(QMessageBox::Cancel);
+  aMessageBox->setEscapeButton(QMessageBox::No); // operation manager should process Esc key
+
+  return aMessageBox;
+}
\ No newline at end of file
index 97cc7426c9b5896fd073f41720d09d00a4104274..81b414fbbfecee4c5ecf0b6ea4457dda48736aab 100755 (executable)
@@ -31,6 +31,7 @@
 #include <QStringList>
 
 class QKeyEvent;
+class QMessageBox;
 
 class ModuleBase_IWorkshop;
 class XGUI_Workshop;
@@ -203,6 +204,11 @@ protected: // TEMPORARY
   /// \param theEvent the mouse event
   bool onKeyReleased(QObject *theObject, QKeyEvent* theEvent);
 
+  /// SLOT, that is called by the key in the property panel is clicked.
+  /// \param theObject a sender of the event
+  /// \param theEvent the mouse event
+  bool onKeyPressed(QObject *theObject, QKeyEvent* theEvent);
+
   /// The functionaly, that should be done by delete click
   /// Fistly the active widget processes it, then workshop. If no one does not
   /// process it, do nothing
@@ -249,6 +255,12 @@ private:
   /// \param theParent a candidate to be a parent
   static bool isChildObject(const QObject* theObject, const QObject* theParent);
 
+  /// Creates question message box with OK/Cancel buttons, where Cancel is default button,
+  /// Escape is Null button
+  /// \param theMessage text of the message
+  /// \return message box
+  static QMessageBox* createMessageBox(const QString& theMessage);
+
  private:
   typedef QList<ModuleBase_Operation*> Operations;  ///< definition for a list of operations
   Operations myOperations;  ///< a stack of started operations. The active operation is on top,
@@ -256,7 +268,7 @@ private:
 
   /// Current workshop
   ModuleBase_IWorkshop* myWorkshop;
-
+  QMessageBox* myActiveMessageBox;
   XGUI_ShortCutListener* myShortCutListener;
   bool mySHIFTPressed;
 };
index 9b1f8cd6c5eebe697bb9af92083507e3956bb26c..72ca9e7d4316ceb6caed3241f7471de66986f4e5 100644 (file)
@@ -22,7 +22,10 @@ INCLUDE(UnitTest)
 
 ADD_UNIT_TESTS_API(
   Primitives/TestBox.py
+  Primitives/TestCone.py
   Primitives/TestCylinder.py
+  Primitives/TestSphere.py
+  Primitives/TestTorus.py
   Primitives/TestAPI_Box.py
   Primitives/TestAPI_Cylinder.py
   GDML/TestConeSegment.py
@@ -32,6 +35,7 @@ ADD_UNIT_TESTS_API(
   Transformations/TestAPI_Scale.py
   Transformations/TestAPI_Symmetry.py
   Transformations/TestAPI_Translation.py
+  Transformations/TestMultiRotation.py
   Transformations/TestMultiTranslation.py
   Transformations/TestRotation.py
   Transformations/TestScale.py
diff --git a/test.API/SHAPER/Primitives/TestCone.py b/test.API/SHAPER/Primitives/TestCone.py
new file mode 100644 (file)
index 0000000..ebe3d50
--- /dev/null
@@ -0,0 +1,106 @@
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+# Init
+Point_1 = model.addPoint(Part_1_doc, 10, 10, 10).result()
+Point_2 = model.selection("VERTEX", "pnt")
+Axis_1 = model.addAxis(Part_1_doc, 0, 10, 0).result()
+Axis_2 = model.selection("EDGE", "edge")
+
+# Parameters
+model.addParameter(Part_1_doc, "baseRadius", "10")
+model.addParameter(Part_1_doc, "topRadius", "7")
+model.addParameter(Part_1_doc, "h", "15")
+
+# Tests
+Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10., 5., 10.)
+Cone_2 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5., 10., 10.)
+Cone_3 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 0., 5., 10.)
+Cone_4 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), -3., 5., 10.)
+Cone_5 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10., 0., 10.)
+Cone_6 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10., -5., 10.)
+Cone_7 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10., 5., 0.)
+Cone_8 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10., 5., -10.)
+Cone_9 = model.addCone(Part_1_doc, Point_1, model.selection("EDGE", "PartSet/OZ"), 10., 7., 15.)
+Cone_10 = model.addCone(Part_1_doc, Point_1, Axis_1, 10., 7., 15.)
+Cone_11 = model.addCone(Part_1_doc, Point_2, model.selection("EDGE", "PartSet/OZ"), 10., 7., 15.)
+Cone_12= model.addCone(Part_1_doc, Point_1, Axis_2, 10., 7., 15.)
+Cone_13 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 0., 0., 15.)
+Cone_14 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10., 10., 15.)
+Cone_15 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "baseRadius", "topRadius", "h")
+
+model.do()
+model.end()
+
+# Checks
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Cone_1, 1)
+model.testNbSubResults(Cone_1, [0])
+model.testNbSubShapes(Cone_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Cone_1, GeomAPI_Shape.FACE, [3])
+model.testHaveNamingFaces(Cone_1, model, Part_1_doc)
+
+model.testNbResults(Cone_2, 1)
+model.testNbSubResults(Cone_2, [0])
+model.testNbSubShapes(Cone_2, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Cone_2, GeomAPI_Shape.FACE, [3])
+model.testHaveNamingFaces(Cone_2, model, Part_1_doc)
+
+model.testNbResults(Cone_3, 1)
+model.testNbSubResults(Cone_3, [0])
+model.testNbSubShapes(Cone_3, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Cone_3, GeomAPI_Shape.FACE, [2])
+model.testHaveNamingFaces(Cone_3, model, Part_1_doc)
+
+model.testNbResults(Cone_5, 1)
+model.testNbSubResults(Cone_5, [0])
+model.testNbSubShapes(Cone_5, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Cone_5, GeomAPI_Shape.FACE, [2])
+model.testHaveNamingFaces(Cone_5, model, Part_1_doc)
+
+model.testNbResults(Cone_9, 1)
+model.testNbSubResults(Cone_9, [0])
+model.testNbSubShapes(Cone_9, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Cone_9, GeomAPI_Shape.FACE, [3])
+model.testHaveNamingFaces(Cone_9, model, Part_1_doc)
+
+model.testNbResults(Cone_10, 1)
+model.testNbSubResults(Cone_10, [0])
+model.testNbSubShapes(Cone_10, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Cone_10, GeomAPI_Shape.FACE, [3])
+model.testHaveNamingFaces(Cone_10, model, Part_1_doc)
+
+model.testNbResults(Cone_15, 1)
+model.testNbSubResults(Cone_15, [0])
+model.testNbSubShapes(Cone_15, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Cone_15, GeomAPI_Shape.FACE, [3])
+model.testHaveNamingFaces(Cone_15, model, Part_1_doc)
+
+model.testNbResults(Cone_4, 0)
+assert(Cone_4.feature().error() == "Cone builder :: base radius is negative.")
+
+model.testNbResults(Cone_6, 0)
+assert(Cone_6.feature().error() == "Cone builder :: top radius is negative.")
+
+model.testNbResults(Cone_7, 0)
+assert(Cone_7.feature().error() == "Cone builder :: height is negative or null.")
+
+model.testNbResults(Cone_8, 0)
+assert(Cone_8.feature().error() == "Cone builder :: height is negative or null.")
+
+model.testNbResults(Cone_11, 0)
+assert(Cone_11.feature().error() == "Attribute \"base_point\" is not initialized.")
+
+model.testNbResults(Cone_12, 0)
+assert(Cone_12.feature().error() == "Attribute \"axis\" is not initialized.")
+
+model.testNbResults(Cone_13, 0)
+assert(Cone_13.feature().error() == "Cone builder :: base radius and top radius are negative or null.")
+
+model.testNbResults(Cone_14, 0)
+assert(Cone_14.feature().error() == "Cone builder :: base radius and top radius are too close.")
diff --git a/test.API/SHAPER/Primitives/TestSphere.py b/test.API/SHAPER/Primitives/TestSphere.py
new file mode 100644 (file)
index 0000000..cf80aab
--- /dev/null
@@ -0,0 +1,54 @@
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+# Init
+Point_1 = model.addPoint(Part_1_doc, 10, 10, 10).result()
+Point_2 = model.selection("VERTEX", "pnt")
+
+# Parameters
+model.addParameter(Part_1_doc, "r", "5")
+
+# Tests
+Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), 10)
+Sphere_2 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), 0)
+Sphere_3 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), -5)
+Sphere_4 = model.addSphere(Part_1_doc, Point_1, 10)
+Sphere_5 = model.addSphere(Part_1_doc, Point_2, 10)
+Sphere_6 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), "r")
+
+model.do()
+model.end()
+
+# Checks
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Sphere_1, 1)
+model.testNbSubResults(Sphere_1, [0])
+model.testNbSubShapes(Sphere_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Sphere_1, GeomAPI_Shape.FACE, [1])
+model.testHaveNamingFaces(Sphere_1, model, Part_1_doc)
+
+model.testNbResults(Sphere_4, 1)
+model.testNbSubResults(Sphere_4, [0])
+model.testNbSubShapes(Sphere_4, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Sphere_4, GeomAPI_Shape.FACE, [1])
+model.testHaveNamingFaces(Sphere_4, model, Part_1_doc)
+
+model.testNbResults(Sphere_6, 1)
+model.testNbSubResults(Sphere_6, [0])
+model.testNbSubShapes(Sphere_6, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Sphere_6, GeomAPI_Shape.FACE, [1])
+model.testHaveNamingFaces(Sphere_4, model, Part_1_doc)
+
+model.testNbResults(Sphere_2, 0)
+assert(Sphere_2.feature().error() == "Sphere builder :: radius is negative or null.")
+
+model.testNbResults(Sphere_3, 0)
+assert(Sphere_3.feature().error() == "Sphere builder :: radius is negative or null.")
+
+model.testNbResults(Sphere_5, 0)
+assert(Sphere_5.feature().error() == "Attribute \"center_point\" is not initialized.")
diff --git a/test.API/SHAPER/Primitives/TestTorus.py b/test.API/SHAPER/Primitives/TestTorus.py
new file mode 100644 (file)
index 0000000..a60d9da
--- /dev/null
@@ -0,0 +1,80 @@
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+# Init
+Point_1 = model.addPoint(Part_1_doc, 10, 10, 10).result()
+Point_2 = model.selection("VERTEX", "pnt")
+Axis_1 = model.addAxis(Part_1_doc, 0, 10, 0).result()
+Axis_2 = model.selection("EDGE", "edge")
+
+# Parameters
+model.addParameter(Part_1_doc, "r", "10")
+model.addParameter(Part_1_doc, "ring", "3")
+
+# Tests
+Torus_1 = model.addTorus(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 15, 3)
+Torus_2 = model.addTorus(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Torus_3 = model.addTorus(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 0, 3)
+Torus_4 = model.addTorus(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), -10, 3)
+Torus_5 = model.addTorus(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 15, 0)
+Torus_6 = model.addTorus(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 15, -3)
+Torus_7 = model.addTorus(Part_1_doc, Point_1, model.selection("EDGE", "PartSet/OX"), 12, 7)
+Torus_8 = model.addTorus(Part_1_doc, Point_1, Axis_1, 15, 4)
+Torus_9 = model.addTorus(Part_1_doc, Point_2, model.selection("EDGE", "PartSet/OZ"), 15, 4)
+Torus_10 = model.addTorus(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), Axis_2, 15, 4)
+Torus_11 = model.addTorus(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "r", "ring")
+
+model.do()
+model.end()
+
+# Checks
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Torus_1, 1)
+model.testNbSubResults(Torus_1, [0])
+model.testNbSubShapes(Torus_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Torus_1, GeomAPI_Shape.FACE, [1])
+model.testHaveNamingFaces(Torus_1, model, Part_1_doc)
+
+model.testNbResults(Torus_7, 1)
+model.testNbSubResults(Torus_7, [0])
+model.testNbSubShapes(Torus_7, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Torus_7, GeomAPI_Shape.FACE, [1])
+model.testHaveNamingFaces(Torus_7, model, Part_1_doc)
+
+model.testNbResults(Torus_8, 1)
+model.testNbSubResults(Torus_8, [0])
+model.testNbSubShapes(Torus_8, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Torus_8, GeomAPI_Shape.FACE, [1])
+model.testHaveNamingFaces(Torus_8, model, Part_1_doc)
+
+model.testNbResults(Torus_11, 1)
+model.testNbSubResults(Torus_11, [0])
+model.testNbSubShapes(Torus_11, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Torus_11, GeomAPI_Shape.FACE, [1])
+model.testHaveNamingFaces(Torus_11, model, Part_1_doc)
+
+model.testNbResults(Torus_2, 0)
+assert(Torus_2.feature().error() == "Torus builder :: ring radius is greater than the radius.")
+
+model.testNbResults(Torus_3, 0)
+assert(Torus_3.feature().error() == "Torus builder :: radius is negative or null.")
+
+model.testNbResults(Torus_4, 0)
+assert(Torus_4.feature().error() == "Torus builder :: radius is negative or null.")
+
+model.testNbResults(Torus_5, 0)
+assert(Torus_5.feature().error() == "Torus builder :: ring radius is negative or null.")
+
+model.testNbResults(Torus_6, 0)
+assert(Torus_6.feature().error() == "Torus builder :: ring radius is negative or null.")
+
+model.testNbResults(Torus_9, 0)
+assert(Torus_9.feature().error() == "Attribute \"base_point\" is not initialized.")
+
+model.testNbResults(Torus_10, 0)
+assert(Torus_10.feature().error() == "Attribute \"axis\" is not initialized.")
diff --git a/test.API/SHAPER/Transformations/TestMultiRotation.py b/test.API/SHAPER/Transformations/TestMultiRotation.py
new file mode 100644 (file)
index 0000000..6cfb625
--- /dev/null
@@ -0,0 +1,84 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+Test case for MultiRotation feature.
+Written on High API.
+"""
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+#Init
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Box_2 = model.addBox(Part_1_doc, 10, 10, 10)
+Box_3 = model.addBox(Part_1_doc, 10, 10, 10)
+Box_4 = model.addBox(Part_1_doc, 10, 10, 10)
+Box_5 = model.addBox(Part_1_doc, 10, 10, 10)
+Box_6 = model.addBox(Part_1_doc, 10, 10, 10)
+Axis_1 = model.selection("EDGE", "edge")
+
+# Tests
+MultiRotation_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OZ"), 5)
+MultiRotation_2 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Box_2_1")], model.selection("EDGE", "PartSet/OZ"), 0)
+MultiRotation_3 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Box_3_1")], model.selection("EDGE", "PartSet/OZ"), -3)
+MultiRotation_4 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Box_4_1")], model.selection("EDGE", "PartSet/OY"), 90, 4)
+MultiRotation_5 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Box_5_1")], model.selection("EDGE", "PartSet/OY"), -75, 4)
+MultiRotation_6 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Box_6_1")], Axis_1, 4)
+
+model.do()
+model.end()
+
+# Check
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(MultiRotation_1, 1)
+model.testNbSubResults(MultiRotation_1, [5])
+model.testNbSubShapes(MultiRotation_1, GeomAPI_Shape.COMPOUND, [1])
+model.testNbSubShapes(MultiRotation_1, GeomAPI_Shape.SOLID, [5])
+model.testNbSubShapes(MultiRotation_1, GeomAPI_Shape.FACE, [30])
+model.testHaveNamingFaces(MultiRotation_1, model, Part_1_doc)
+
+model.testNbResults(MultiRotation_4, 1)
+model.testNbSubResults(MultiRotation_4, [4])
+model.testNbSubShapes(MultiRotation_4, GeomAPI_Shape.COMPOUND, [1])
+model.testNbSubShapes(MultiRotation_4, GeomAPI_Shape.SOLID, [4])
+model.testNbSubShapes(MultiRotation_4, GeomAPI_Shape.FACE, [24])
+model.testHaveNamingFaces(MultiRotation_4, model, Part_1_doc)
+
+model.testNbResults(MultiRotation_5, 1)
+model.testNbSubResults(MultiRotation_5, [4])
+model.testNbSubShapes(MultiRotation_5, GeomAPI_Shape.COMPOUND, [1])
+model.testNbSubShapes(MultiRotation_5, GeomAPI_Shape.SOLID, [4])
+model.testNbSubShapes(MultiRotation_5, GeomAPI_Shape.FACE, [24])
+model.testHaveNamingFaces(MultiRotation_5, model, Part_1_doc)
+
+model.testNbResults(MultiRotation_2, 0)
+assert(MultiRotation_2.feature().error() == "Multirotation builder :: the number of copies for the angular direction is null or negative.")
+
+model.testNbResults(MultiRotation_3, 0)
+assert(MultiRotation_3.feature().error() == "Multirotation builder :: the number of copies for the angular direction is null or negative.")
+
+model.testNbResults(MultiRotation_6, 0)
+assert(MultiRotation_6.feature().error() == "Attribute \"axis_angular\" is not initialized.")
index 7fad6c9ba8b35d433e81c04ca3c6cbc91d71e123..d078b73aff40e15499e7a44926aeba990ad8c2d0 100644 (file)
@@ -117,6 +117,18 @@ model.testNbSubShapes(Rotation_4, GeomAPI_Shape.SOLID, [1])
 model.testNbSubShapes(Rotation_4, GeomAPI_Shape.FACE, [6])
 model.testHaveNamingFaces(Rotation_4, model, Part_1_doc)
 
+model.testNbResults(Rotation_5, 1)
+model.testNbSubResults(Rotation_5, [0])
+model.testNbSubShapes(Rotation_5, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Rotation_5, GeomAPI_Shape.FACE, [6])
+model.testHaveNamingFaces(Rotation_5, model, Part_1_doc)
+
+model.testNbResults(Rotation_6, 1)
+model.testNbSubResults(Rotation_6, [0])
+model.testNbSubShapes(Rotation_6, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Rotation_6, GeomAPI_Shape.FACE, [6])
+model.testHaveNamingFaces(Rotation_6, model, Part_1_doc)
+
 model.testNbResults(Rotation_9, 1)
 model.testNbSubResults(Rotation_9, [0])
 model.testNbSubShapes(Rotation_9, GeomAPI_Shape.SOLID, [1])
@@ -136,11 +148,13 @@ model.testNbResults(Rotation_19, 1)
 model.testNbSubResults(Rotation_19, [0])
 
 
-model.testNbResults(Rotation_5, 0)
-assert(Rotation_5.feature().error() == 'Rotation builder :: angle greater than 360 degrees.')
+# This test is OK because we accept angles greater than 360
+#model.testNbResults(Rotation_5, 0)
+#assert(Rotation_5.feature().error() == 'Rotation builder :: angle greater than 360 degrees.')
 
-model.testNbResults(Rotation_6, 0)
-assert(Rotation_6.feature().error() == 'Rotation builder :: angle smaller than -360 degrees.')
+# This test is OK because we accept angles smaller than 360
+#model.testNbResults(Rotation_6, 0)
+#assert(Rotation_6.feature().error() == 'Rotation builder :: angle smaller than -360 degrees.')
 
 model.testNbResults(Rotation_7, 0)
 assert(Rotation_7.feature().error() == 'Attribute "axis_object" is not initialized.')
@@ -173,4 +187,4 @@ assert(Rotation_16.feature().error() == 'Attribute "start_point" is not initiali
 #assert(Rotation_8.feature().error() == 'Attribute "main_object" is not initialized.')
 
 #model.testNbResults(Rotation_17, 0)
-#assert(Rotation_17.feature().error() == 'Attribute "main_object" is not initialized.')
\ No newline at end of file
+#assert(Rotation_17.feature().error() == 'Attribute "main_object" is not initialized.')