]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge with Dev_1.5.0
authorspo <sergey.pokhodenko@opencascade.com>
Tue, 3 Nov 2015 14:12:45 +0000 (17:12 +0300)
committerspo <sergey.pokhodenko@opencascade.com>
Tue, 3 Nov 2015 14:12:45 +0000 (17:12 +0300)
88 files changed:
.gitignore
env_linux.sh
src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.h
src/Model/Model_AttributeRefAttr.h
src/Model/Model_AttributeSelection.cpp
src/ModelAPI/ModelAPI.i
src/ModelAPI/ModelAPI_AttributeSelection.h
src/ModelAPI/ModelAPI_AttributeSelectionList.h
src/ModelAPI/ModelAPI_Document.h
src/ModelAPI/ModelAPI_Feature.h
src/PartSetPlugin/PartSetPlugin_Part.cpp
src/PythonAPI/CMakeLists.txt
src/PythonAPI/MakeBrick1.py [deleted file]
src/PythonAPI/MakeBrick2.py [deleted file]
src/PythonAPI/MakeBrick3.py [deleted file]
src/PythonAPI/Test/TestFeaturesExtrusion.py [new file with mode: 0644]
src/PythonAPI/Test/TestFeaturesRevolution.py [new file with mode: 0644]
src/PythonAPI/Test/TestMakeBrick1.py [new file with mode: 0644]
src/PythonAPI/Test/TestMakeBrick2.py [new file with mode: 0644]
src/PythonAPI/Test/TestMakeBrick3.py [new file with mode: 0644]
src/PythonAPI/Test/TestModel.py [new file with mode: 0644]
src/PythonAPI/Test/TestShaper.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcher.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherAddArc.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherAddCircle.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherAddLine.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherAddPoint.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherSetAngle.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherSetCoincident.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherSetEqual.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherSetFillet.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherSetHorizontal.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherSetLength.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherSetParallel.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherSetPerpendicular.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherSetRadius.py [new file with mode: 0644]
src/PythonAPI/Test/TestSketcherSetVertical.py [new file with mode: 0644]
src/PythonAPI/examples/MakeBrick1.py [new file with mode: 0644]
src/PythonAPI/examples/MakeBrick2.py [new file with mode: 0644]
src/PythonAPI/examples/MakeBrick3.py [new file with mode: 0644]
src/PythonAPI/examples/__init__.py [new file with mode: 0644]
src/PythonAPI/extension/__init__.py
src/PythonAPI/extension/box.py
src/PythonAPI/model/__init__.py [new file with mode: 0644]
src/PythonAPI/model/connection/__init__.py [new file with mode: 0644]
src/PythonAPI/model/connection/connection.py [new file with mode: 0644]
src/PythonAPI/model/construction/__init__.py [new file with mode: 0644]
src/PythonAPI/model/construction/axis.py [new file with mode: 0644]
src/PythonAPI/model/construction/plane.py [new file with mode: 0644]
src/PythonAPI/model/construction/point.py [new file with mode: 0644]
src/PythonAPI/model/errors.py [new file with mode: 0644]
src/PythonAPI/model/exchange/__init__.py [new file with mode: 0644]
src/PythonAPI/model/exchange/exchange.py [new file with mode: 0644]
src/PythonAPI/model/features/__init__.py [new file with mode: 0644]
src/PythonAPI/model/features/boolean.py [new file with mode: 0644]
src/PythonAPI/model/features/extrusion.py [new file with mode: 0644]
src/PythonAPI/model/features/extrusion_boolean.py [new file with mode: 0644]
src/PythonAPI/model/features/extrusion_sketch.py [new file with mode: 0644]
src/PythonAPI/model/features/group.py [new file with mode: 0644]
src/PythonAPI/model/features/partition.py [new file with mode: 0644]
src/PythonAPI/model/features/placement.py [new file with mode: 0644]
src/PythonAPI/model/features/revolution.py [new file with mode: 0644]
src/PythonAPI/model/features/revolution_boolean.py [new file with mode: 0644]
src/PythonAPI/model/features/revolution_sketch.py [new file with mode: 0644]
src/PythonAPI/model/features/roots.py [new file with mode: 0644]
src/PythonAPI/model/features/rotation.py [new file with mode: 0644]
src/PythonAPI/model/features/translation.py [new file with mode: 0644]
src/PythonAPI/model/parameter/__init__.py [new file with mode: 0644]
src/PythonAPI/model/parameter/parameter.py [new file with mode: 0644]
src/PythonAPI/model/partset/__init__.py [new file with mode: 0644]
src/PythonAPI/model/partset/part.py [new file with mode: 0644]
src/PythonAPI/model/roots.py [new file with mode: 0644]
src/PythonAPI/model/services.py [new file with mode: 0644]
src/PythonAPI/model/sketcher/__init__.py [new file with mode: 0644]
src/PythonAPI/model/sketcher/arc.py [new file with mode: 0644]
src/PythonAPI/model/sketcher/circle.py [new file with mode: 0644]
src/PythonAPI/model/sketcher/line.py [new file with mode: 0644]
src/PythonAPI/model/sketcher/point.py [new file with mode: 0644]
src/PythonAPI/model/sketcher/sketch.py [new file with mode: 0644]
src/PythonAPI/model/tools.py [new file with mode: 0644]
src/PythonAPI/modeler/__init__.py [deleted file]
src/PythonAPI/modeler/services.py [deleted file]
src/PythonAPI/pylintrc [new file with mode: 0644]
src/PythonAPI/shaper.py [new file with mode: 0644]
src/PythonAddons/addons_Features.py
src/PythonAddons/macros/box/feature.py
src/SketchPlugin/SketchPlugin_Point.h
src/SketchPlugin/plugin-Sketch.xml

index b3e5bb13fb16b3cafc9c15e28bdc11ef91562fb4..3361c41de623b070d566e552f43cb77123319d36 100644 (file)
@@ -29,4 +29,4 @@ start.bat
 *~
 /.project
 *DFBrowser*
-
+*.pyc
index 379bdd24c0acdb28eaccf2fd6166be3170dcb83a..8d6cdc892908ecdd31b2699d5cedd5c405102274 100644 (file)
@@ -39,7 +39,7 @@ export PATH=${CASROOT}:${PATH}
 
 #------ NewGEOM ------
 export PATH=${NEWGEOM_ROOT_DIR}/bin:${NEWGEOM_ROOT_DIR}/plugins:${PATH}
-export PYTHONPATH=${NEWGEOM_ROOT_DIR}/swig:${NEWGEOM_ROOT_DIR}/plugins:${NEWGEOM_ROOT_DIR}/addons:${NEWGEOM_ROOT_DIR}/pythonAPI:${PYTHONPATH}
+export PYTHONPATH=${NEWGEOM_ROOT_DIR}/swig:${NEWGEOM_ROOT_DIR}/plugins:${NEWGEOM_ROOT_DIR}/addons:${NEWGEOM_ROOT_DIR}/PythonAPI:${PYTHONPATH}
 export LD_LIBRARY_PATH=${NEWGEOM_ROOT_DIR}/bin:${NEWGEOM_ROOT_DIR}/swig:${NEWGEOM_ROOT_DIR}/plugins:${LD_LIBRARY_PATH}
 export NEW_GEOM_CONFIG_FILE=${NEWGEOM_ROOT_DIR}/plugins
 export NewGeomResources=${NEWGEOM_ROOT_DIR}/resources
index 806a004cd1770ce2467f592860615a93c939f1b1..1ad620eb49a6b320c08ef16935ed813d02110150 100644 (file)
@@ -52,7 +52,7 @@ class FeaturesPlugin_CompositeSketch : public ModelAPI_CompositeFeature
   /// \return the sub-feature unique identifier in this composite feature by zero-base index.
   FEATURESPLUGIN_EXPORT virtual int subFeatureId(const int theIndex) const;
 
-  /// \return true if feature or reuslt belong to this composite feature as subs.
+  /// \return true if feature or result belong to this composite feature as subs.
   FEATURESPLUGIN_EXPORT virtual bool isSub(ObjectPtr theObject) const;
 
   /// This method to inform that sub-feature is removed and must be removed from the internal data
index 49337e695a9e7ebae3b79a944271b6a3d2b72f52..40e3e0ecbec066380b0252fb7a6c89088558037a 100644 (file)
@@ -22,7 +22,7 @@
 class Model_AttributeRefAttr : public ModelAPI_AttributeRefAttr
 {
   Handle_TDF_Reference myRef;  ///< reference to the feature label
-  ///< ID of the referenced attirbute (empty if this is a reference to a feature)
+  ///< ID of the referenced attribute (empty if this is a reference to a feature)
   Handle_TDataStd_Comment myID;
  public:
   /// Returns true if this attribute references to a object (not to the attribute)
index 232ff61b558ead55e47049e9d23208513d06c975..d8fbc9878a5b3bb5c5164558499c75ee41a50296 100644 (file)
@@ -61,7 +61,7 @@ using namespace std;
 #ifdef DEB_NAMING
 #include <BRepTools.hxx>
 #endif
-/// adeed to the index in the packed map to signalize that the vertex of edge is seleted
+/// added to the index in the packed map to signalize that the vertex of edge is selected
 /// (multiplied by the index of the edge)
 static const int kSTART_VERTEX_DELTA = 1000000;
 // identifier that there is simple reference: selection equals to context
@@ -239,7 +239,7 @@ bool Model_AttributeSelection::isInvalid()
 
 bool Model_AttributeSelection::isInitialized()
 {
-  if (ModelAPI_AttributeSelection::isInitialized()) { // additional checkings if it is initialized
+  if (ModelAPI_AttributeSelection::isInitialized()) { // additional checks if it is initialized
     std::shared_ptr<GeomAPI_Shape> aResult;
     if (myRef.isInitialized()) {
       TDF_Label aSelLab = selectionLabel();
@@ -312,7 +312,7 @@ void Model_AttributeSelection::setObject(const std::shared_ptr<ModelAPI_Object>&
 TDF_LabelMap& Model_AttributeSelection::scope()
 {
   if (myScope.IsEmpty()) { // create a new scope if not yet done
-    // gets all featueres with named shapes that are bofore this feature label (before in history)
+    // gets all features with named shapes that are before this feature label (before in history)
     DocumentPtr aMyDoc = owner()->document();
     std::list<std::shared_ptr<ModelAPI_Feature> > allFeatures = aMyDoc->allFeatures();
     std::list<std::shared_ptr<ModelAPI_Feature> >::iterator aFIter = allFeatures.begin();
@@ -458,7 +458,7 @@ bool Model_AttributeSelection::update()
         if (aNoIndexes) {
           aNewSelected = aConstructionContext->face(0);
         } else { // searching for most looks-like initial face by the indexes
-          // prepare edges of the current resut for the fast searching
+          // prepare edges of the current result for the fast searching
           NCollection_DataMap<Handle(Geom_Curve), int> allCurves; // curves and orientations of edges
           const int aSubNum = aComposite->numberOfSubs();
           for(int a = 0; a < aSubNum; a++) {
@@ -670,7 +670,7 @@ static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape,
       aName<<"f";
     else if (theOrientation == -1)
       aName<<"r";
-  } else { // make a compisite name from all sub-elements indexes: "1_2_3_4"
+  } else { // make a composite name from all sub-elements indexes: "1_2_3_4"
     TColStd_MapIteratorOfPackedMapOfInteger aRef(theRefs->GetMap());
     for(; aRef.More(); aRef.Next()) {
       aName<<"-"<<aRef.Key();
@@ -706,7 +706,7 @@ void Model_AttributeSelection::selectConstruction(
   }
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(owner()->data());
   TDF_Label aLab = myRef.myRef->Label();
-  // identify the reuslts of sub-object of the composite by edges
+  // identify the results of sub-object of the composite by edges
   // save type of the selected shape in integer attribute
   TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType();
   TDataStd_Integer::Set(aLab, (int)aShapeType);
@@ -826,7 +826,7 @@ bool Model_AttributeSelection::selectPart(
     }
     return true; // nothing to do, referencing just by name
   }
-  // store the shape (in case part is not loaded it should be usefull
+  // store the shape (in case part is not loaded it should be useful
   TopoDS_Shape aShape;
   std::string aName = theContext->data()->name();
   if (!theSubShape.get() || theSubShape->isNull()) {// the whole part shape is selected
index 7da97d0c182ff97c2324541f1e984eb16cd2ca3e..8da7ce250a1cf8dc59f3137f4df441fd48551590 100644 (file)
@@ -22,6 +22,7 @@
   #include "ModelAPI_AttributeDocRef.h"
   #include "ModelAPI_AttributeDouble.h"
   #include "ModelAPI_AttributeInteger.h"
+  #include "ModelAPI_AttributeIntArray.h"
   #include "ModelAPI_AttributeString.h"
   #include "ModelAPI_AttributeReference.h"
   #include "ModelAPI_AttributeRefAttr.h"
@@ -83,6 +84,7 @@
 %shared_ptr(ModelAPI_AttributeDocRef)
 %shared_ptr(ModelAPI_AttributeDouble)
 %shared_ptr(ModelAPI_AttributeInteger)
+%shared_ptr(ModelAPI_AttributeIntArray)
 %shared_ptr(ModelAPI_AttributeString)
 %shared_ptr(ModelAPI_AttributeReference)
 %shared_ptr(ModelAPI_AttributeRefAttr)
 %include "ModelAPI_AttributeDocRef.h"
 %include "ModelAPI_AttributeDouble.h"
 %include "ModelAPI_AttributeInteger.h"
+%include "ModelAPI_AttributeIntArray.h"
 %include "ModelAPI_AttributeString.h"
 %include "ModelAPI_AttributeReference.h"
 %include "ModelAPI_AttributeRefAttr.h"
@@ -156,6 +159,7 @@ template<class T1, class T2> std::shared_ptr<T1> shared_ptr_cast(std::shared_ptr
 %template(modelAPI_AttributeDocRef)        shared_ptr_cast<ModelAPI_AttributeDocRef, ModelAPI_Attribute>;
 %template(modelAPI_AttributeDouble)        shared_ptr_cast<ModelAPI_AttributeDouble, ModelAPI_Attribute>;
 %template(modelAPI_AttributeInteger)       shared_ptr_cast<ModelAPI_AttributeInteger, ModelAPI_Attribute>;
+%template(modelAPI_AttributeIntArray)      shared_ptr_cast<ModelAPI_AttributeIntArray, ModelAPI_Attribute>;
 %template(modelAPI_AttributeString)        shared_ptr_cast<ModelAPI_AttributeString, ModelAPI_Attribute>;
 %template(modelAPI_AttributeReference)     shared_ptr_cast<ModelAPI_AttributeReference, ModelAPI_Attribute>;
 %template(modelAPI_AttributeRefAttr)       shared_ptr_cast<ModelAPI_AttributeRefAttr, ModelAPI_Attribute>;
index fccb6b018f8196d1b89644390f35d3861a8a6449..61b1979a0b2c1643f126059a716fe8b556948649 100644 (file)
@@ -57,7 +57,7 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute
   /// Selects sub-shape by the textual Name
   virtual void selectSubShape(const std::string& theType, const std::string& theSubShapeName) = 0;
 
-  /// Returns true if recomute of selection become impossible
+  /// Returns true if recompute of selection become impossible
   virtual bool isInvalid() = 0;
 
   /// To virtually destroy the fields of successors
index e2cad1e1f7404176c8209cf3ecc6b91f0aaa1740..52eec8ca15ab35acd71cbb4cffacd4a53d133b53 100644 (file)
@@ -23,7 +23,7 @@ class ModelAPI_AttributeSelectionList : public ModelAPI_Attribute
   /// \param theContext object where the sub-shape was selected
   /// \param theSubShape selected sub-shape (if null, the whole context is selected)
   /// \param theTemporarily if it is true, do not store and name the added in the data framework
-  ///           (used to remove immideately, without the following updates)
+  ///           (used to remove immediately, without the following updates)
   virtual void append(const ResultPtr& theContext,
                       const GeomShapePtr& theSubShape,
                       const bool theTemporarily = false) = 0;
index 4edc005c95ef320cd3cbb13d242d89116ac723a9..abf679546fa7ffdf410cfced299d96af3fdbbb58 100644 (file)
@@ -122,7 +122,7 @@ public:
   //! To virtually destroy the fields of successors
   MODELAPI_EXPORT virtual ~ModelAPI_Document();
 
-  //! Creates a construction cresult
+  //! Creates a construction result
   virtual std::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
       const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0) = 0;
   //! Creates a body result
index af55636cb58e7b573d2f5cf1235e16d5bff53f22..8a648e7c53c21616a7260ed5ad29ec0d11f2628c 100644 (file)
@@ -85,7 +85,7 @@ class ModelAPI_Feature : public ModelAPI_Object
                                  const int theIndex);
   /// removes the result from the feature
   MODELAPI_EXPORT void removeResult(const std::shared_ptr<ModelAPI_Result>& theResult);
-  /// removes all results starting from the gived index (zero-based)
+  /// removes all results starting from the given index (zero-based)
   /// \param theSinceIndex - index of the deleted result and all after also will be deleted
   /// \param theFlush - if it is false, REDISPLAY message is not flushed
   MODELAPI_EXPORT void removeResults(const int theSinceIndex, const bool theFlush = true);
index 794fcd4fa2a58a459ac81a0cb302d1d87055721f..31759862f1fe20f53d1bc72133dc191f94c8772e 100644 (file)
@@ -31,8 +31,8 @@ void PartSetPlugin_Part::execute()
     // do not activate part by simple execution if it is not loaded yet: it must be explicitly
     // activated for this
     if (!ModelAPI_Session::get()->isLoadByDemand(aResult->data()->name())) {
-      // On undo/redo creation of the part result the Object Borwser must get creation event
-      // earlier that activation of this part event (otherwise the crash is producted)
+      // On undo/redo creation of the part result the Object Browser must get creation event
+      // earlier that activation of this part event (otherwise the crash is produced)
       // So, send a creation event earlier, without any grouping
       static Events_ID aCreateID = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
       ModelAPI_EventCreator::get()->sendUpdated(aResult, aCreateID, false);
index c89a7986859a74850eae271b9d9adb61d49b8778..376853dfbb10d196618d6c877b61713f3820e20b 100644 (file)
@@ -3,4 +3,36 @@
 
 SET(CMAKE_AUTOMOC ON)
 
-INSTALL(DIRECTORY extension geom modeler DESTINATION pythonAPI)
+INSTALL(DIRECTORY extension geom model examples DESTINATION PythonAPI)
+INSTALL(FILES shaper.py DESTINATION PythonAPI)
+
+# --------- Unit tests -----------
+INCLUDE(UnitTest)
+
+ADD_UNIT_TESTS(
+  TestShaper.py
+  TestModel.py
+
+  TestSketcherAddPoint.py
+  TestSketcherAddLine.py
+  TestSketcherAddArc.py
+  TestSketcherAddCircle.py
+  TestSketcherSetCoincident.py
+  TestSketcherSetParallel.py
+  TestSketcherSetPerpendicular.py
+  TestSketcherSetHorizontal.py
+  TestSketcherSetVertical.py
+  TestSketcherSetLength.py
+  TestSketcherSetRadius.py
+  TestSketcherSetAngle.py
+  TestSketcherSetEqual.py
+  TestSketcherSetFillet.py
+
+  TestFeatures.py
+  TestFeaturesExtrusion.py
+  TestFeaturesRevolution.py
+
+  TestMakeBrick1.py
+  TestMakeBrick2.py
+#  TestMakeBrick3.py
+  )
diff --git a/src/PythonAPI/MakeBrick1.py b/src/PythonAPI/MakeBrick1.py
deleted file mode 100644 (file)
index 8320de0..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# Creation of a box using the end-user API
-# Author: Daniel Brunier-Coulin
-# -----------------------------
-
-import modeler
-
-
-# Initialisation
-
-modeler.begin()
-mypartset = modeler.moduleDocument()
-
-
-# Creating a new Part
-
-mypart = modeler.addPart(mypartset).document()
-
-
-# Creating the base of the box
-
-mybase = modeler.addSketch( mypart, modeler.defaultPlane("XOY") )
-
-l1 = mybase.addLine( 0, 0, 0, 1 )
-l2 = mybase.addLine( 0, 1, 1, 1 )
-l3 = mybase.addLine( 1, 1, 1, 0 )
-l4 = mybase.addLine( 1, 0, 0, 0 )
-
-mybase.setCoincident( l1.endPointData(), l2.startPointData() )
-mybase.setCoincident( l2.endPointData(), l3.startPointData() )
-mybase.setCoincident( l3.endPointData(), l4.startPointData() )
-mybase.setCoincident( l4.endPointData(), l1.startPointData() )
-
-mybase.setParallel( l1.result(), l3.result() )
-mybase.setParallel( l2.result(), l4.result() )
-
-mybase.setPerpendicular( l1.result(), l4.result() )
-
-mywidth  = mybase.setLength( l1.result(), 50 )
-mylength = mybase.setDistance( l1.startPointData(), l3.result(), 50 )
-
-
-# Creating the extrusion
-
-mybox = modeler.addExtrusion( mypart, mybase.selectFace(), 50 )
-
-
-# Creating a cylinder on a face of the box
-
-thisface = "Extrusion_1/LateralFace_2"
-thisxmin = "Extrusion_1/LateralFace_3|Extrusion_1/LateralFace_2"
-thisxmax = "Extrusion_1/LateralFace_2|Extrusion_1/LateralFace_1"
-thiszmin = "Sketch_1/Edge5_1"
-thiszmax = "Extrusion_1/LateralFace_2|Extrusion_1/TopFace_1"
-
-mystand = modeler.addSketch( mypart, thisface )
-c1      = mystand.addCircle( 0, 25, 5)
-mystand.setDistance( c1.centerData(), thisxmin, 10 )
-mystand.setDistance( c1.centerData(), thiszmax, 10 )
-
-myboss = modeler.addExtrusion( mypart, mystand.selectFace(c1.result()), -5 )
-
-
-# Subtracting the cylinder to the box
-
-modeler.addSubtraction( mypart, mybox.result(), myboss.result() )
-modeler.end()
-
-
-# Editing the box
-
-modeler.begin()
-mybase.setValue( mylength, 100 )
-mybox.setSize( 80 )
-modeler.end()
diff --git a/src/PythonAPI/MakeBrick2.py b/src/PythonAPI/MakeBrick2.py
deleted file mode 100644 (file)
index 24865b5..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-# Creation of a box using the end-user API
-# Author: Daniel Brunier-Coulin
-# -----------------------------
-
-import modeler
-import geom
-
-
-# Initialisation
-
-modeler.begin()
-mypartset = modeler.moduleDocument()
-
-
-# Creating a new Part
-
-mypart = modeler.addPart(mypartset).document()
-
-
-# Creating the base of the box
-
-mybase = modeler.addSketch( mypart, modeler.defaultPlane("XOY") )
-
-p1 = geom.Pnt2d( 0, 0 )
-p2 = geom.Pnt2d( 0, 1 )
-p3 = geom.Pnt2d( 1, 1 )
-p4 = geom.Pnt2d( 1, 0 )
-
-line = mybase.addPolygon(p1, p2, p3, p4)
-
-mybase.setParallel( line[0].result(), line[2].result() )
-mybase.setParallel( line[1].result(), line[3].result() )
-mybase.setPerpendicular( line[0].result(), line[3].result() )
-
-mywidth  = mybase.setLength( line[0].result(), 50 )
-mylength = mybase.setDistance( line[0].startPointData(),line[2].result(), 50 )
-
-
-# Creating the extrusion
-
-mybox = modeler.addExtrusion( mypart, mybase.selectFace(), 50 )
-
-
-# Creating a cylinder on a face of the box
-
-thisface = "Extrusion_1/LateralFace_2"
-thisxmin = "Extrusion_1/LateralFace_3|Extrusion_1/LateralFace_2"
-thiszmax = "Extrusion_1/LateralFace_2|Extrusion_1/TopFace_1"
-
-mystand = modeler.addSketch( mypart, thisface )
-circle  = mystand.addCircle( 0, 25, 5)
-mystand.setDistance( circle.centerData(), thisxmin, 10 )
-mystand.setDistance( circle.centerData(), thiszmax, 10 )
-
-myboss = modeler.addExtrusion( mypart, mystand.selectFace(), -5 )
-
-
-# Subtracting the cylinder to the box
-
-modeler.addSubtraction( mypart, mybox.result(), myboss.result() )
-modeler.end()
-
-
-# Editing the box
-
-modeler.begin()
-mybase.setValue( mylength, 100 )
-mybox.setSize( 20 )
-modeler.end()
diff --git a/src/PythonAPI/MakeBrick3.py b/src/PythonAPI/MakeBrick3.py
deleted file mode 100644 (file)
index c314780..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-# Creation of a box using the end-user API
-# Author: Daniel Brunier-Coulin
-# -----------------------------
-
-import modeler
-import extension
-
-
-# Initialisation
-
-modeler.begin()
-mypartset = modeler.moduleDocument()
-
-
-# Creating a new Part
-
-mypart = modeler.addPart(mypartset).document()
-
-
-# Creating the base of the box
-
-extension.addBox( mypart, 10, 20, 30 )
-modeler.end()
-
diff --git a/src/PythonAPI/Test/TestFeaturesExtrusion.py b/src/PythonAPI/Test/TestFeaturesExtrusion.py
new file mode 100644 (file)
index 0000000..decd198
--- /dev/null
@@ -0,0 +1,159 @@
+import unittest
+
+import ModelAPI
+
+import model
+
+#-----------------------------------------------------------------------------
+# Fixtures
+
+class FeaturesAddExtrusionFixture(unittest.TestCase):
+
+    def setUp(self):
+        model.begin()
+        # Create part
+        partset = model.moduleDocument()
+        self.part = model.addPart(partset).document()
+        model.do()
+
+    def tearDown(self):
+        model.end()
+        model.reset()
+
+
+class FeaturesExtrusionFixture(FeaturesAddExtrusionFixture):
+
+    def setUp(self):
+        FeaturesAddExtrusionFixture.setUp(self)
+        # Create extrusion
+        sketch = model.addSketch(self.part, model.defaultPlane("XOY"))
+        circle = sketch.addCircle(0, 0, 10)
+        model.do()
+
+        base = sketch.selectFace(circle.result())
+        self.extrusion = model.addExtrusion(self.part, base, 10, 0)
+        model.do()
+
+    def tearDown(self):
+        FeaturesAddExtrusionFixture.tearDown(self)
+
+#-----------------------------------------------------------------------------
+# TestCases
+
+class FeaturesAddExtrusionTestCase(FeaturesAddExtrusionFixture):
+
+    def test_add_extrusion_no_base(self):
+        try:
+            extrusion = model.addExtrusion(self.part)
+            fail("addExtrusion should assert if base is not None")
+        except AssertionError:
+            pass
+
+    def test_add_extrusion_by_face_and_size(self):
+        sketch = model.addSketch(self.part, model.defaultPlane("XOY"))
+        circle = sketch.addCircle(0, 0, 10)
+        model.do()
+
+        base = sketch.selectFace(circle.result())
+        extrusion = model.addExtrusion(self.part, base, 10, 0)
+        model.do()
+
+        self.assertEqual(extrusion.getCreationMethod().value(), "BySizes")
+        self.assertEqual(extrusion.getToSize().value(), 10)
+        self.assertEqual(extrusion.getFromSize().value(), 0)
+        self.assertEqual(extrusion.getToObject().context(), None)
+        self.assertEqual(extrusion.getToOffset().value(), 0)
+        self.assertEqual(extrusion.getFromObject().context(), None)
+        self.assertEqual(extrusion.getFromOffset().value(), 0)
+
+    def test_add_extrusion_by_face_and_planes(self):
+        # base
+        base_sketch = model.addSketch(self.part, model.defaultPlane("XOY"))
+        base_circle = base_sketch.addCircle(0, 0, 10)
+        # to
+        to_plane = model.defaultPlane("XOY")
+        to_plane.location().setZ(10)
+        to_sketch = model.addSketch(self.part, to_plane)
+        to_circle = to_sketch.addCircle(0, 0, 10)
+        # from
+        from_plane = model.defaultPlane("XOY")
+        from_plane.location().setZ(-10)
+        from_sketch = model.addSketch(self.part, from_plane)
+        from_circle = from_sketch.addCircle(0, 0, 10)
+
+        model.do()
+
+        base = base_sketch.selectFace(base_circle.result())
+        to_object = to_sketch.selectFace(to_circle.result())[0]
+        from_object = from_sketch.selectFace(from_circle.result())[0]
+        extrusion = model.addExtrusion(self.part, base,
+                                       to_object, 15,
+                                       from_object, 20)
+
+        self.assertEqual(extrusion.getCreationMethod().value(), "ByPlanesAndOffsets")
+        self.assertEqual(extrusion.getToSize().value(), 0)
+        self.assertEqual(extrusion.getFromSize().value(), 0)
+#         self.assertEqual(extrusion.getToObject().context(),
+#                          to_sketch.result())
+        self.assertEqual(extrusion.getToOffset().value(), 15)
+#         self.assertEqual(extrusion.getFromObject().context(),
+#                          from_sketch.result())
+        self.assertEqual(extrusion.getFromOffset().value(), 20)
+
+
+class FeaturesExtrusionTestCase(FeaturesExtrusionFixture):
+
+    def test_extrusion_feature_calls(self):
+        # call method of the feature
+        self.assertEqual(self.extrusion.getKind(), "Extrusion")
+
+    def test_extrusion_get_attribute(self):
+        # call method of the feature
+        self.assertTrue(isinstance(self.extrusion.getBase(),
+                                   ModelAPI.ModelAPI_AttributeSelectionList))
+        self.assertTrue(isinstance(self.extrusion.getCreationMethod(),
+                                   ModelAPI.ModelAPI_AttributeString))
+        self.assertTrue(isinstance(self.extrusion.getToSize(),
+                                   ModelAPI.ModelAPI_AttributeDouble))
+        self.assertTrue(isinstance(self.extrusion.getFromSize(),
+                                   ModelAPI.ModelAPI_AttributeDouble))
+        self.assertTrue(isinstance(self.extrusion.getToObject(),
+                                   ModelAPI.ModelAPI_AttributeSelection))
+        self.assertTrue(isinstance(self.extrusion.getToOffset(),
+                                   ModelAPI.ModelAPI_AttributeDouble))
+        self.assertTrue(isinstance(self.extrusion.getFromObject(),
+                                   ModelAPI.ModelAPI_AttributeSelection))
+        self.assertTrue(isinstance(self.extrusion.getFromOffset(),
+                                   ModelAPI.ModelAPI_AttributeDouble))
+
+    def test_extrusion_set_sizes(self):
+        self.extrusion.setSizes(15, 20)
+        self.assertEqual(self.extrusion.getCreationMethod().value(), "BySizes")
+        self.assertEqual(self.extrusion.getToSize().value(), 15)
+        self.assertEqual(self.extrusion.getFromSize().value(), 20)
+        self.assertEqual(self.extrusion.getToObject().context(), None)
+        self.assertEqual(self.extrusion.getToOffset().value(), 0)
+        self.assertEqual(self.extrusion.getFromObject().context(), None)
+        self.assertEqual(self.extrusion.getFromOffset().value(), 0)
+
+    def test_extrusion_set_planes_and_offsets(self):
+        # to
+        to_plane = model.defaultPlane("XOY")
+        to_plane.location().setZ(10)
+        to_sketch = model.addSketch(self.part, to_plane)
+        to_circle = to_sketch.addCircle(0, 0, 10)
+        # from
+        from_plane = model.defaultPlane("XOY")
+        from_plane.location().setZ(-10)
+        from_sketch = model.addSketch(self.part, from_plane)
+        from_circle = from_sketch.addCircle(0, 0, 10)
+
+        model.do()
+
+        to_object = to_sketch.selectFace(to_circle.result())[0]
+        from_object = from_sketch.selectFace(from_circle.result())[0]
+        self.extrusion.setPlanesAndOffsets(to_object, 15, from_object, 20)
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/PythonAPI/Test/TestFeaturesRevolution.py b/src/PythonAPI/Test/TestFeaturesRevolution.py
new file mode 100644 (file)
index 0000000..a7fbfde
--- /dev/null
@@ -0,0 +1,204 @@
+import unittest
+
+import ModelAPI
+
+import model
+from model.tools import Selection
+
+#-----------------------------------------------------------------------------
+# Fixtures
+
+class FeaturesAddRevolutionFixture(unittest.TestCase):
+
+    def setUp(self):
+        model.begin()
+        # Create part
+        partset = model.moduleDocument()
+        self.part = model.addPart(partset).document()
+        model.do()
+
+    def tearDown(self):
+        model.end()
+        model.reset()
+
+
+class FeaturesRevolutionFixture(FeaturesAddRevolutionFixture):
+
+    def setUp(self):
+        FeaturesAddRevolutionFixture.setUp(self)
+        # Create revolution
+        # base
+        base_sketch = model.addSketch(self.part, model.defaultPlane("XOY"))
+        circle = base_sketch.addCircle(0, 0, 10)
+        # axis
+        axis_sketch = model.addSketch(self.part, model.defaultPlane("XOY"))
+        line = axis_sketch.addLine(20, -10, 20, 10)
+
+        model.do()
+
+        base = base_sketch.selectFace(circle.lastResult())
+        axis_object = Selection(axis_sketch.firstResult(),
+                                line.firstResult().shape())
+
+        self.revolution = model.addRevolution(self.part, base, axis_object,
+                                              0, 180)
+
+        model.do()
+
+    def tearDown(self):
+        FeaturesAddRevolutionFixture.tearDown(self)
+
+#-----------------------------------------------------------------------------
+# TestCases
+
+class FeaturesAddRevolutionTestCase(FeaturesAddRevolutionFixture):
+
+    def test_add_revolution_no_base(self):
+        try:
+            revolution = model.addRevolution(self.part)
+            fail("addRevolution should assert if base is not None")
+        except AssertionError:
+            pass
+
+    def test_add_revolution_by_face_and_angles(self):
+        # base
+        base_sketch = model.addSketch(self.part, model.defaultPlane("XOY"))
+        circle = base_sketch.addCircle(0, 0, 10)
+        # axis
+        axis_sketch = model.addSketch(self.part, model.defaultPlane("XOY"))
+        line = axis_sketch.addLine(20, -10, 20, 10)
+
+        model.do()
+
+        base = base_sketch.selectFace(circle.lastResult())
+        axis_object = Selection(axis_sketch.firstResult(),
+                                line.firstResult().shape())
+
+        revolution = model.addRevolution(self.part, base, axis_object,
+                                         0, 180)
+
+        self.assertEqual(revolution.getCreationMethod().value(), "ByAngles")
+        self.assertEqual(revolution.getToAngle().value(), 0)
+        self.assertEqual(revolution.getFromAngle().value(), 180)
+        self.assertEqual(revolution.getToObject().context(), None)
+        self.assertEqual(revolution.getToOffset().value(), 0)
+        self.assertEqual(revolution.getFromObject().context(), None)
+        self.assertEqual(revolution.getFromOffset().value(), 0)
+
+    def test_add_revolution_by_face_and_planes(self):
+        # base
+        base_sketch = model.addSketch(self.part, model.defaultPlane("XOY"))
+        base_circle = base_sketch.addCircle(0, 0, 10)
+        # axis
+        axis_sketch = model.addSketch(self.part, model.defaultPlane("XOY"))
+        line = axis_sketch.addLine(20, -10, 20, 10)
+        # to
+        to_plane = model.defaultPlane("XOY")
+        to_plane.location().setZ(10)
+        to_sketch = model.addSketch(self.part, to_plane)
+        to_circle = to_sketch.addCircle(0, 0, 10)
+        # from
+        from_plane = model.defaultPlane("XOY")
+        from_plane.location().setZ(-10)
+        from_sketch = model.addSketch(self.part, from_plane)
+        from_circle = from_sketch.addCircle(0, 0, 10)
+
+        model.do()
+
+        base = base_sketch.selectFace(base_circle.result())
+        axis_object = Selection(axis_sketch.firstResult(),
+                                line.firstResult().shape())
+        to_obejct = to_sketch.selectFace(to_circle.result())[0]
+        from_object = from_sketch.selectFace(from_circle.result())[0]
+
+        revolution = model.addRevolution(self.part, base, axis_object,
+                                         to_obejct, 15,
+                                         from_object, 20)
+
+        self.assertEqual(revolution.getCreationMethod().value(), "ByPlanesAndOffsets")
+        self.assertEqual(revolution.getToAngle().value(), 0)
+        self.assertEqual(revolution.getFromAngle().value(), 0)
+#         self.assertEqual(revolution.getToObject().context(),
+#                          to_sketch.result())
+        self.assertEqual(revolution.getToOffset().value(), 15)
+#         self.assertEqual(revolution.getFromObject().context(),
+#                          from_sketch.result())
+        self.assertEqual(revolution.getFromOffset().value(), 20)
+
+
+class FeaturesRevolutionTestCase(FeaturesRevolutionFixture):
+
+    def test_revolution_feature_calls(self):
+        # call method of the feature
+        self.assertEqual(self.revolution.getKind(), "Revolution")
+
+    def test_revolution_get_attribute(self):
+        # call method of the feature
+        self.assertTrue(isinstance(self.revolution.getBase(),
+                                   ModelAPI.ModelAPI_AttributeSelectionList))
+        self.assertTrue(isinstance(self.revolution.getAxisObject(),
+                                   ModelAPI.ModelAPI_AttributeSelection))
+        self.assertTrue(isinstance(self.revolution.getCreationMethod(),
+                                   ModelAPI.ModelAPI_AttributeString))
+        self.assertTrue(isinstance(self.revolution.getToAngle(),
+                                   ModelAPI.ModelAPI_AttributeDouble))
+        self.assertTrue(isinstance(self.revolution.getFromAngle(),
+                                   ModelAPI.ModelAPI_AttributeDouble))
+        self.assertTrue(isinstance(self.revolution.getToObject(),
+                                   ModelAPI.ModelAPI_AttributeSelection))
+        self.assertTrue(isinstance(self.revolution.getToOffset(),
+                                   ModelAPI.ModelAPI_AttributeDouble))
+        self.assertTrue(isinstance(self.revolution.getFromObject(),
+                                   ModelAPI.ModelAPI_AttributeSelection))
+        self.assertTrue(isinstance(self.revolution.getFromOffset(),
+                                   ModelAPI.ModelAPI_AttributeDouble))
+
+    def test_revolution_set_angles(self):
+        self.revolution.setAngles(90, 270)
+        self.assertEqual(self.revolution.getCreationMethod().value(), "ByAngles")
+        self.assertEqual(self.revolution.getToAngle().value(), 90)
+        self.assertEqual(self.revolution.getFromAngle().value(), 270)
+        self.assertEqual(self.revolution.getToObject().context(), None)
+        self.assertEqual(self.revolution.getToOffset().value(), 0)
+        self.assertEqual(self.revolution.getFromObject().context(), None)
+        self.assertEqual(self.revolution.getFromOffset().value(), 0)
+
+    def test_revolution_set_planes_and_offsets(self):
+        # base
+        base_sketch = model.addSketch(self.part, model.defaultPlane("XOY"))
+        base_circle = base_sketch.addCircle(0, 0, 10)
+        # axis
+        axis_sketch = model.addSketch(self.part, model.defaultPlane("XOY"))
+        line = axis_sketch.addLine(20, -10, 20, 10)
+        # to
+        to_plane = model.defaultPlane("XOY")
+        to_plane.location().setZ(10)
+        to_sketch = model.addSketch(self.part, to_plane)
+        to_circle = to_sketch.addCircle(0, 0, 10)
+        # from
+        from_plane = model.defaultPlane("XOY")
+        from_plane.location().setZ(-10)
+        from_sketch = model.addSketch(self.part, from_plane)
+        from_circle = from_sketch.addCircle(0, 0, 10)
+
+        model.do()
+
+        base = base_sketch.selectFace(base_circle.result())
+        axis_object = Selection(axis_sketch.firstResult(),
+                                line.firstResult().shape())
+        to_obejct = to_sketch.selectFace(to_circle.result())[0]
+        from_object = from_sketch.selectFace(from_circle.result())[0]
+
+        self.revolution.setPlanesAndOffsets(to_obejct, 15, from_object, 20)
+
+        self.assertEqual(self.revolution.getCreationMethod().value(), "ByPlanesAndOffsets")
+        self.assertEqual(self.revolution.getToAngle().value(), 0)
+        self.assertEqual(self.revolution.getFromAngle().value(), 0)
+#         self.assertEqual(self.revolution.getToObject().context(), None)
+        self.assertEqual(self.revolution.getToOffset().value(), 15)
+#         self.assertEqual(self.revolution.getFromObject().context(), None)
+        self.assertEqual(self.revolution.getFromOffset().value(), 20)
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/PythonAPI/Test/TestMakeBrick1.py b/src/PythonAPI/Test/TestMakeBrick1.py
new file mode 100644 (file)
index 0000000..2225919
--- /dev/null
@@ -0,0 +1,6 @@
+import unittest
+
+import examples.MakeBrick1
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/PythonAPI/Test/TestMakeBrick2.py b/src/PythonAPI/Test/TestMakeBrick2.py
new file mode 100644 (file)
index 0000000..21ea726
--- /dev/null
@@ -0,0 +1,6 @@
+import unittest
+
+import examples.MakeBrick2
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/PythonAPI/Test/TestMakeBrick3.py b/src/PythonAPI/Test/TestMakeBrick3.py
new file mode 100644 (file)
index 0000000..bbdb4a9
--- /dev/null
@@ -0,0 +1,6 @@
+import unittest
+
+import examples.MakeBrick3
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/PythonAPI/Test/TestModel.py b/src/PythonAPI/Test/TestModel.py
new file mode 100644 (file)
index 0000000..d763777
--- /dev/null
@@ -0,0 +1,18 @@
+import unittest
+import model
+
+class ModelTestCase(unittest.TestCase):
+    def setUp(self):
+        model.begin()
+        partset = model.moduleDocument()
+        self.part = model.addPart(partset).document()
+
+    def tearDown(self):
+        model.end()
+
+    def test_add_sketch(self):
+        plane = model.defaultPlane("XOY")
+        model.addSketch(self.part, plane)
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/PythonAPI/Test/TestShaper.py b/src/PythonAPI/Test/TestShaper.py
new file mode 100644 (file)
index 0000000..09c751b
--- /dev/null
@@ -0,0 +1,6 @@
+import unittest
+from shaper import model
+from shaper import geom
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/PythonAPI/Test/TestSketcher.py b/src/PythonAPI/Test/TestSketcher.py
new file mode 100644 (file)
index 0000000..b48337b
--- /dev/null
@@ -0,0 +1,16 @@
+import unittest
+import model
+
+# Delta value for almost equal comparisons
+DELTA = 1e-10
+
+class SketcherTestCase(unittest.TestCase):
+    def setUp(self):
+        model.begin()
+        partset = model.moduleDocument()
+        part = model.addPart(partset).document()
+        plane = model.defaultPlane("XOY")
+        self.sketch = model.addSketch(part, plane)
+
+    def tearDown(self):
+        model.end()
diff --git a/src/PythonAPI/Test/TestSketcherAddArc.py b/src/PythonAPI/Test/TestSketcherAddArc.py
new file mode 100644 (file)
index 0000000..9b433f0
--- /dev/null
@@ -0,0 +1,46 @@
+import unittest
+
+import model
+import geom
+from model import WrongNumberOfArguments
+
+from TestSketcher import SketcherTestCase
+
+class SketcherAddArc(SketcherTestCase):    
+    def test_arc_by_coords(self):
+        arc = self.sketch.addArc(0, 1, 0, 0, 1, 1)
+        model.do()
+        self.assertEqual(arc.startPointData().x(), 0)        
+        self.assertEqual(arc.startPointData().y(), 0)
+    
+    def test_arc_by_points(self):
+        center = geom.Pnt2d(0, 1)
+        start = geom.Pnt2d(0, 0)
+        end = geom.Pnt2d(1, 1)
+        arc = self.sketch.addArc(center, start, end)
+        model.do()
+        self.assertEqual(arc.startPointData().x(), 0)        
+        self.assertEqual(arc.startPointData().y(), 0)
+    
+    def test_number_of_args(self):
+        with self.assertRaises(WrongNumberOfArguments):
+            self.sketch.addArc(0, 1, 1, 1)
+        with self.assertRaises(WrongNumberOfArguments):
+            self.sketch.addArc(0, 1)
+            
+    def test_modify_arc(self):
+        arc = self.sketch.addArc(0, 1, 0, 0, 1, 1)
+        arc.setCenter(0, 0)
+        arc.setStartPoint(-1.0, 0)
+        arc.setEndPoint(0, 1.0)
+        model.do()
+        self.assertEqual(arc.centerData().x(), 0)        
+        self.assertEqual(arc.centerData().y(), 0)
+        self.assertEqual(arc.startPointData().x(), -1)        
+        self.assertEqual(arc.startPointData().y(), 0)
+        self.assertEqual(arc.endPointData().x(), 0)        
+        self.assertEqual(arc.endPointData().y(), 1)
+        
+    
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherAddCircle.py b/src/PythonAPI/Test/TestSketcherAddCircle.py
new file mode 100644 (file)
index 0000000..932bb68
--- /dev/null
@@ -0,0 +1,25 @@
+import unittest
+import model
+from TestSketcher import SketcherTestCase
+
+class SketcherAddCircle(SketcherTestCase):    
+    def test_add_cricle(self):
+        circle = self.sketch.addCircle(0, 10, 20)
+        model.do()
+        self.assertEqual(circle.centerData().x(), 0.0)        
+        self.assertEqual(circle.centerData().y(), 10.0)
+        self.assertEqual(circle.radiusData().value(), 20.0)
+        
+    def test_modify_circle(self):
+        circle = self.sketch.addCircle(0, 10, 20)
+        model.do()
+        circle.setCenter(10, 10)
+        circle.setRadius(30)
+        model.do()
+        self.assertEqual(circle.centerData().x(), 10.0)        
+        self.assertEqual(circle.centerData().y(), 10.0)
+        self.assertEqual(circle.radiusData().value(), 30.0)
+        
+    
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherAddLine.py b/src/PythonAPI/Test/TestSketcherAddLine.py
new file mode 100644 (file)
index 0000000..fa4ed94
--- /dev/null
@@ -0,0 +1,24 @@
+import unittest
+import model
+from TestSketcher import SketcherTestCase
+
+class SketcherAddLine(SketcherTestCase):    
+    def test_add_line(self):
+        line = self.sketch.addLine(0, 0, 0, 1)
+        model.do()
+        self.assertEqual(line.getStartPoint().x(), line.getEndPoint().x())        
+        self.assertNotEqual(line.getStartPoint().y(), line.getEndPoint().y())
+
+    def test_modify_line(self):
+        line = self.sketch.addLine(0, 0, 0, 1)
+        model.do()
+        line.setStartPoint(0, 1)
+        line.setEndPoint(1, 1)
+        self.assertEqual(line.getStartPoint().x(), 0)
+        self.assertEqual(line.getStartPoint().y(), 1)
+        self.assertEqual(line.getEndPoint().x(), 1)
+        self.assertEqual(line.getEndPoint().y(), 1)
+
+
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherAddPoint.py b/src/PythonAPI/Test/TestSketcherAddPoint.py
new file mode 100644 (file)
index 0000000..198887b
--- /dev/null
@@ -0,0 +1,21 @@
+import unittest
+import model
+from TestSketcher import SketcherTestCase
+
+class SketcherAddPoint(SketcherTestCase):    
+    def test_add_point(self):
+        point = self.sketch.addPoint(0, 1)
+        model.do()
+        self.assertEqual(point.pointData().x(), 0.0)        
+        self.assertEqual(point.pointData().y(), 1.0)
+        
+    def test_modify_point(self):
+        point = self.sketch.addPoint(0, 1)
+        point.setValue(1, 2)
+        model.do()
+        self.assertEqual(point.pointData().x(), 1.0)        
+        self.assertEqual(point.pointData().y(), 2.0)
+        
+    
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherSetAngle.py b/src/PythonAPI/Test/TestSketcherSetAngle.py
new file mode 100644 (file)
index 0000000..cbdd5fc
--- /dev/null
@@ -0,0 +1,34 @@
+import unittest
+import model
+import math
+import TestSketcher
+from TestSketcher import SketcherTestCase
+
+class SketcherSetAngle(SketcherTestCase):   
+    def runTest(self):
+        # Set the constraint
+        l1 = self.sketch.addLine(0, 0, 0, 1)
+        l2 = self.sketch.addLine(0, 0, 1, 1)
+        self.sketch.setAngle(l1.result(), l2.result(), 30.0)
+        # Commit the transaction
+        model.do()
+        # Check the result
+        dot_product = (l1.endPointData().x() - l1.startPointData().x()) * \
+                      (l2.endPointData().x() - l2.startPointData().x()) + \
+                      (l1.endPointData().y() - l1.startPointData().y()) * \
+                      (l2.endPointData().y() - l2.startPointData().y())
+        norm_1 = math.sqrt(
+            math.pow((l1.endPointData().x() - l1.startPointData().x()), 2) + 
+            math.pow((l1.endPointData().y() - l1.startPointData().y()), 2)
+            )
+        norm_2 = math.sqrt(
+            math.pow((l2.endPointData().x() - l2.startPointData().x()), 2) + 
+            math.pow((l2.endPointData().y() - l2.startPointData().y()), 2)
+            )
+        angle = math.acos(dot_product / (norm_1 * norm_2))
+        self.assertAlmostEqual(
+            angle * 180 / math.pi, 30.0, delta=TestSketcher.DELTA
+            )
+        
+if __name__ == "__main__":
+    unittest.main()
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherSetCoincident.py b/src/PythonAPI/Test/TestSketcherSetCoincident.py
new file mode 100644 (file)
index 0000000..a5c07f7
--- /dev/null
@@ -0,0 +1,13 @@
+import unittest
+import model
+from TestSketcher import SketcherTestCase
+
+class SketcherSetCoincident(SketcherTestCase):   
+    def runTest(self):
+        l1 = self.sketch.addLine(0, 0, 0, 1)
+        l2 = self.sketch.addLine(0, 1, 1, 1)
+        self.sketch.setCoincident(l1.endPointData(), l2.startPointData())
+        model.do()
+
+if __name__ == "__main__":
+    unittest.main()
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherSetEqual.py b/src/PythonAPI/Test/TestSketcherSetEqual.py
new file mode 100644 (file)
index 0000000..4965629
--- /dev/null
@@ -0,0 +1,42 @@
+import unittest
+import model
+import math
+import TestSketcher
+from TestSketcher import SketcherTestCase
+
+class SketcherSetEqual(SketcherTestCase):
+    def test_length_equality(self):
+        # Set the constraint
+        l1 = self.sketch.addLine(0, 0, 0, 1)
+        l2 = self.sketch.addLine(0, 0, 1, 1)
+        self.sketch.setEqual(l1.result(), l2.result())
+        # Commit the transaction
+        model.do()
+        # Check the result
+        length_1 = math.sqrt(
+            math.pow((l1.endPointData().x() - l1.startPointData().x()), 2) +
+            math.pow((l1.endPointData().y() - l1.startPointData().y()), 2)
+            )
+        length_2 = math.sqrt(
+            math.pow((l2.endPointData().x() - l2.startPointData().x()), 2) +
+            math.pow((l2.endPointData().y() - l2.startPointData().y()), 2)
+            )
+        self.assertAlmostEqual(length_1, length_2, delta=TestSketcher.DELTA)
+
+    def test_radius_equality(self):
+        # Set the constraint
+        circle_1 = self.sketch.addCircle(0, 0, 10.0)
+        circle_2 = self.sketch.addCircle(1, 2, 25.0)
+        self.sketch.setEqual(circle_1.result(), circle_2.result())
+        # Commit the transaction
+        model.do()
+        # Check the result
+        self.assertAlmostEqual(
+            circle_1.radiusData().value(),
+            circle_2.radiusData().value(),
+            delta=TestSketcher.DELTA
+            )
+
+if __name__ == "__main__":
+    suite = unittest.TestLoader().loadTestsFromTestCase(SketcherSetEqual)
+    unittest.TextTestRunner(verbosity=2).run(suite)
diff --git a/src/PythonAPI/Test/TestSketcherSetFillet.py b/src/PythonAPI/Test/TestSketcherSetFillet.py
new file mode 100644 (file)
index 0000000..f84b67a
--- /dev/null
@@ -0,0 +1,14 @@
+import unittest
+import model
+from TestSketcher import SketcherTestCase
+
+class SketcherSetFillet(SketcherTestCase):   
+    def runTest(self):
+        l1 = self.sketch.addLine(0, 0, 0, 1)
+        l2 = self.sketch.addLine(0, 1, 1, 1)
+        self.sketch.setCoincident(l1.endPointData(), l2.startPointData())
+        self.sketch.setFillet(l1.result(), l2.result(), 10.0)
+        model.do()
+
+if __name__ == "__main__":
+    unittest.main()
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherSetHorizontal.py b/src/PythonAPI/Test/TestSketcherSetHorizontal.py
new file mode 100644 (file)
index 0000000..0b795e7
--- /dev/null
@@ -0,0 +1,13 @@
+import unittest
+import model
+from TestSketcher import SketcherTestCase
+
+class SketcherSetHorizontal(SketcherTestCase):   
+    def runTest(self):
+        line = self.sketch.addLine(0, 0, 1, 1)
+        self.sketch.setHorizontal(line.result())
+        model.do()
+        self.assertEqual(line.startPointData().y(), line.endPointData().y())
+
+if __name__ == "__main__":
+    unittest.main()
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherSetLength.py b/src/PythonAPI/Test/TestSketcherSetLength.py
new file mode 100644 (file)
index 0000000..b56650b
--- /dev/null
@@ -0,0 +1,22 @@
+import unittest
+import model
+import math
+import TestSketcher
+from TestSketcher import SketcherTestCase
+
+class SketcherSetLength(SketcherTestCase):   
+    def runTest(self):
+        # Set the constraint
+        line = self.sketch.addLine(0, 0, 0, 1)
+        self.sketch.setLength(line.result(), 25.0)
+        # Commit the transaction
+        model.do()
+        # Check the result
+        length = math.sqrt(
+            math.pow((line.endPointData().x() - line.startPointData().x()), 2) + 
+            math.pow((line.endPointData().y() - line.startPointData().y()), 2)
+            )
+        self.assertAlmostEqual(length, 25.0, delta=TestSketcher.DELTA)
+        
+if __name__ == "__main__":
+    unittest.main()
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherSetParallel.py b/src/PythonAPI/Test/TestSketcherSetParallel.py
new file mode 100644 (file)
index 0000000..75c37ec
--- /dev/null
@@ -0,0 +1,13 @@
+import unittest
+import model
+from TestSketcher import SketcherTestCase
+
+class SketcherSetParallel(SketcherTestCase):   
+    def runTest(self):
+        l1 = self.sketch.addLine(0, 0, 0, 1)
+        l2 = self.sketch.addLine(0, 1, 1, 1)
+        self.sketch.setParallel(l1.result(), l2.result())
+        model.do()
+
+if __name__ == "__main__":
+    unittest.main()
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherSetPerpendicular.py b/src/PythonAPI/Test/TestSketcherSetPerpendicular.py
new file mode 100644 (file)
index 0000000..b572d9e
--- /dev/null
@@ -0,0 +1,21 @@
+import unittest
+import model
+import TestSketcher
+from TestSketcher import SketcherTestCase
+
+class SketcherSetPerpendicular(SketcherTestCase):
+    """Test case for prependicular constraint testing."""
+    def runTest(self):
+        l1 = self.sketch.addLine(0, 0, 0, 1)
+        l2 = self.sketch.addLine(0, 0, 1, 1)
+        self.sketch.setPerpendicular(l1.result(), l2.result())
+        model.do()
+        
+        dot_product = (l1.endPointData().x() - l1.startPointData().x()) * \
+                      (l2.endPointData().x() - l2.startPointData().x()) + \
+                      (l1.endPointData().y() - l1.startPointData().y()) * \
+                      (l2.endPointData().y() - l2.startPointData().y())
+        self.assertAlmostEqual(dot_product, 0.0, delta=TestSketcher.DELTA)
+
+if __name__ == "__main__":
+    unittest.main()
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherSetRadius.py b/src/PythonAPI/Test/TestSketcherSetRadius.py
new file mode 100644 (file)
index 0000000..def3979
--- /dev/null
@@ -0,0 +1,21 @@
+import unittest
+import model
+from TestSketcher import SketcherTestCase
+
+class SketcherSetRadius(SketcherTestCase):   
+    def test_set_radius(self):
+        circle = self.sketch.addCircle(0, 10, 20)
+        self.sketch.setRadius(circle.result(), 30)
+        model.do()
+        self.assertEqual(circle.radiusData().value(), 30.0)
+        
+    def test_modify_radius(self):
+        circle = self.sketch.addCircle(0, 10, 20)
+        radius = self.sketch.setRadius(circle.result(), 30)
+        model.do()
+        self.sketch.setValue(radius, 20)
+        model.do()
+        self.assertEqual(circle.radiusData().value(), 20.0)
+        
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
\ No newline at end of file
diff --git a/src/PythonAPI/Test/TestSketcherSetVertical.py b/src/PythonAPI/Test/TestSketcherSetVertical.py
new file mode 100644 (file)
index 0000000..cda9f6c
--- /dev/null
@@ -0,0 +1,13 @@
+import unittest
+import model
+from TestSketcher import SketcherTestCase
+
+class SketcherSetVertical(SketcherTestCase):   
+    def runTest(self):
+        line = self.sketch.addLine(0, 0, 1, 1)
+        self.sketch.setVertical(line.result())
+        model.do()
+        self.assertEqual(line.startPointData().x(), line.endPointData().x())
+
+if __name__ == "__main__":
+    unittest.main()
\ No newline at end of file
diff --git a/src/PythonAPI/examples/MakeBrick1.py b/src/PythonAPI/examples/MakeBrick1.py
new file mode 100644 (file)
index 0000000..dd064fb
--- /dev/null
@@ -0,0 +1,72 @@
+# Creation of a box using the end-user API
+# Author: Daniel Brunier-Coulin
+# -----------------------------
+
+import model
+
+
+# Initialisation
+
+model.begin()
+mypartset = model.moduleDocument()
+
+
+# Creating a new Part
+
+mypart = model.addPart(mypartset).document()
+
+
+# Creating the base of the box
+
+mybase = model.addSketch( mypart, model.defaultPlane("XOY") )
+
+l1 = mybase.addLine( 0, 0, 0, 1 )
+l2 = mybase.addLine( 0, 1, 1, 1 )
+l3 = mybase.addLine( 1, 1, 1, 0 )
+l4 = mybase.addLine( 1, 0, 0, 0 )
+
+mybase.setCoincident( l1.endPointData(), l2.startPointData() )
+mybase.setCoincident( l2.endPointData(), l3.startPointData() )
+mybase.setCoincident( l3.endPointData(), l4.startPointData() )
+mybase.setCoincident( l4.endPointData(), l1.startPointData() )
+
+mybase.setParallel( l1.result(), l3.result() )
+mybase.setParallel( l2.result(), l4.result() )
+
+mybase.setPerpendicular( l1.result(), l4.result() )
+
+mywidth  = mybase.setLength( l1.result(), 50 )
+mylength = mybase.setDistance( l1.startPointData(), l3.result(), 50 )
+
+# Creating the extrusion
+
+mybox = model.addExtrusion( mypart, mybase.selectFace(), 50 )
+
+# Creating a cylinder on a face of the box
+
+thisface = "Extrusion_1_1/LateralFace_2"
+thisxmin = "Extrusion_1_1/LateralFace_3|Extrusion_1_1/LateralFace_2"
+thisxmax = "Extrusion_1_1/LateralFace_2|Extrusion_1_1/LateralFace_1"
+thiszmin = "Sketch_1/Edge5_1"
+thiszmax = "Extrusion_1_1/LateralFace_2|Extrusion_1_1/ToFace_1"
+
+mystand = model.addSketch( mypart, thisface )
+
+c1      = mystand.addCircle( 0, 25, 5)
+mystand.setDistance( c1.centerData(), thisxmin, 10 )
+mystand.setDistance( c1.centerData(), thiszmax, 10 )
+
+myboss = model.addExtrusion( mypart, mystand.selectFace(c1.result()), -5 )
+
+# Subtracting the cylinder to the box
+
+model.addSubtraction( mypart, mybox.result(), myboss.result() )
+model.end()
+
+
+# Editing the box
+
+model.begin()
+mybase.setValue( mylength, 100 )
+mybox.setSize( 80 )
+model.end()
diff --git a/src/PythonAPI/examples/MakeBrick2.py b/src/PythonAPI/examples/MakeBrick2.py
new file mode 100644 (file)
index 0000000..2fa09d6
--- /dev/null
@@ -0,0 +1,69 @@
+# Creation of a box using the end-user API
+# Author: Daniel Brunier-Coulin
+# -----------------------------
+
+import model
+import geom
+
+
+# Initialisation
+
+model.begin()
+mypartset = model.moduleDocument()
+
+
+# Creating a new Part
+
+mypart = model.addPart(mypartset).document()
+
+
+# Creating the base of the box
+
+mybase = model.addSketch(mypart, model.defaultPlane("XOY"))
+
+p1 = geom.Pnt2d(0, 0)
+p2 = geom.Pnt2d(0, 1)
+p3 = geom.Pnt2d(1, 1)
+p4 = geom.Pnt2d(1, 0)
+
+line = mybase.addPolygon(p1, p2, p3, p4)
+
+mybase.setParallel(line[0].result(), line[2].result())
+mybase.setParallel(line[1].result(), line[3].result())
+mybase.setPerpendicular(line[0].result(), line[3].result())
+
+mywidth = mybase.setLength(line[0].result(), 50)
+mylength = mybase.setDistance(line[0].startPointData(), line[2].result(), 50)
+
+
+# Creating the extrusion
+
+mybox = model.addExtrusion(mypart, mybase.selectFace(), 50)
+
+
+# Creating a cylinder on a face of the box
+
+thisface = "Extrusion_1_1/LateralFace_2"
+thisxmin = "Extrusion_1_1/LateralFace_3|Extrusion_1_1/LateralFace_2"
+thiszmax = "Extrusion_1_1/LateralFace_2|Extrusion_1_1/ToFace_1"
+
+mystand = model.addSketch(mypart, thisface)
+circle = mystand.addCircle(0, 25, 5)
+mystand.setDistance(circle.centerData(), thisxmin, 10)
+mystand.setDistance(circle.centerData(), thiszmax, 10)
+
+myboss = model.addExtrusion(mypart, mystand.selectFace(), -5)
+
+
+# Subtracting the cylinder to the box
+
+model.addSubtraction(mypart, mybox.result(), myboss.result())
+model.end()
+
+
+# Editing the box
+
+model.begin()
+mybase.setValue(mylength, 100)
+mybox.setSize(20)
+model.end()
diff --git a/src/PythonAPI/examples/MakeBrick3.py b/src/PythonAPI/examples/MakeBrick3.py
new file mode 100644 (file)
index 0000000..94fa252
--- /dev/null
@@ -0,0 +1,24 @@
+# Creation of a box using the end-user API
+# Author: Daniel Brunier-Coulin
+# -----------------------------
+
+import model
+import extension
+
+
+# Initialisation
+
+model.begin()
+mypartset = model.moduleDocument()
+
+
+# Creating a new Part
+
+mypart = model.addPart(mypartset).document()
+
+
+# Creating the base of the box
+
+extension.addBox( mypart, 10, 20, 30 )
+model.end()
+
diff --git a/src/PythonAPI/examples/__init__.py b/src/PythonAPI/examples/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
index 275cb5503abd07913295db07906df76748d0cc5b..b57f516a153db5d92ce347bbc0406bdcadf51905 100644 (file)
@@ -1,4 +1,4 @@
 """User-defined features.
 """
 
-from box import Box as addBox
\ No newline at end of file
+from box import addBox
\ No newline at end of file
index 3a6b641a58b8581097a5530b5ebe91d916e74fc8..c3ef9dcbcbe2c40af7f8dde370f332db0d104108 100644 (file)
@@ -3,22 +3,64 @@ Author: Daniel Brunier-Coulin
 Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 """
 
-import modeler
+from model import Interface
 from macros.box.feature import BoxFeature as MY
 
 
-class Box(modeler.Interface):
-  """Executes the macro-feature Box.
-  """
-  def __init__(self, part, dx, dy, dz):
-    """Constructor"""
-    modeler.Interface.__init__(self, part, MY.ID())
+def addBox(part, *args):
+    """Add Box feature to the part and return Box.
 
-    self.setRealInput( MY.WIDTH_ID(), dx )
-    self.setRealInput( MY.LENGTH_ID(), dy )
-    self.setRealInput( MY.HEIGHT_ID(), dz )
+    Pass all args to Box __init__ function.
+    """
+    feature = part.addFeature(MY.ID())
+    return Box(feature, *args)
 
-    if self.areInputValid():
-      self.execute()
-    else:
-      raise Exception("cannot make the Box")
\ No newline at end of file
+
+class Box(Interface):
+    """Executes the macro-feature Box.
+
+    Box(feature) -> feature interface without initialization
+    Extrusion(feature, dx, dy, dz) ->
+        feature interface initialized from arguments:
+        - dx, dy, dz -- box dimensions
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == MY.ID())
+
+        self._width = self._feature.real(MY.WIDTH_ID())
+        self._length = self._feature.real(MY.LENGTH_ID())
+        self._height = self._feature.real(MY.HEIGHT_ID())
+
+        assert(self._width)
+        assert(self._length)
+        assert(self._height)
+
+        if not args:
+            return
+
+        assert(len(args) == 3)
+        dx, dy, dz = args
+        self.setWidth(dx)
+        self.setLength(dy)
+        self.setHeight(dz)
+
+        self.execute()
+        pass
+
+    def setWidth(self, width):
+        """B.setWidth(float) -- modify width attribute"""
+        self._fillAttribute(self._width, width)
+        pass
+
+    def setLength(self, length):
+        """B.setLength(float) -- modify length attribute"""
+        self._fillAttribute(self._length, length)
+        pass
+
+    def setHeight(self, height):
+        """B.setHeight(float) -- modify height attribute"""
+        self._fillAttribute(self._height, height)
+        pass
diff --git a/src/PythonAPI/model/__init__.py b/src/PythonAPI/model/__init__.py
new file mode 100644 (file)
index 0000000..3a8c553
--- /dev/null
@@ -0,0 +1,28 @@
+"""This package defines the Parametric Geometry API of the Modeler.
+
+All features are available via model.add*() functions. Exceptions are:
+- exportToFile() - from Exchange plugin
+- duplicatePart(), removePart() - from PartSet plugin
+- exportToGEOM() - from Connection plugin
+"""
+
+# General purpose functions and abstract root classes
+
+from services  import *
+from roots     import *
+from tools import Selection
+
+# Built-in features
+
+from sketcher.sketch  import addSketch
+from connection import *
+from construction import *
+from exchange import *
+from features import *
+from parameter import *
+from partset import *
+
+# Custom exceptions
+
+from errors import WrongNumberOfArguments
+from errors import FeatureInputInvalid
diff --git a/src/PythonAPI/model/connection/__init__.py b/src/PythonAPI/model/connection/__init__.py
new file mode 100644 (file)
index 0000000..514b7f9
--- /dev/null
@@ -0,0 +1,4 @@
+"""Package for Connection plugin for the Parametric Geometry API of the Modeler.
+"""
+
+from connection import exportToGEOM
\ No newline at end of file
diff --git a/src/PythonAPI/model/connection/connection.py b/src/PythonAPI/model/connection/connection.py
new file mode 100644 (file)
index 0000000..65e6252
--- /dev/null
@@ -0,0 +1,12 @@
+"""Export to GEOM Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def exportToGEOM(part):
+    """Export the Part to GEOM module."""
+    feature = part.addFeature("ExportToGEOM")
+    feature.execute()
\ No newline at end of file
diff --git a/src/PythonAPI/model/construction/__init__.py b/src/PythonAPI/model/construction/__init__.py
new file mode 100644 (file)
index 0000000..e56746d
--- /dev/null
@@ -0,0 +1,6 @@
+"""Package for Construction plugin for the Parametric Geometry API of the Modeler.
+"""
+
+from point import addPoint
+from axis import addAxis
+from plane import addPlane
diff --git a/src/PythonAPI/model/construction/axis.py b/src/PythonAPI/model/construction/axis.py
new file mode 100644 (file)
index 0000000..2c510be
--- /dev/null
@@ -0,0 +1,84 @@
+"""Axis Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def addAxis(part, *args):
+    """Add an Axis feature to the Part and return Axis.
+
+    Pass all args to Axis __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("Axis")
+    return Axis(feature, *args)
+
+
+class Axis(Interface):
+    """Interface class for Axis feature.
+
+    Axis(feature) -> feature interface without initialization
+    Axis(feature, p1, p2) ->
+        feature interface initialized from arguments:
+        - p1 -- FirstPoint
+        - p2 -- SecondPoint
+    Axis(feature, face) ->
+        feature interface initialized from arguments:
+        - face -- CylindricalFace
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Axis")
+
+        self._CreationMethod = self._feature.data().string("CreationMethod")
+        self._FirstPoint = self._feature.data().selection("FirstPoint")
+        self._SecondPoint = self._feature.data().selection("SecondPoint")
+        self._CylindricalFace = self._feature.data().selection("CylindricalFace")
+
+        assert(self._CreationMethod)
+        assert(self._FirstPoint)
+        assert(self._SecondPoint)
+        assert(self._CylindricalFace)
+
+        if not args:
+            return
+
+        assert(len(args) in (1, 2))
+        if len(args) == 2:
+            self.setPoints(*args)
+        elif len(args) == 1:
+            self.setCylindricalFace(*args)
+
+        self.execute()
+        pass
+
+    def __clear(self):
+        self._fillAttribute(self._CreationMethod, "AxisByPointsCase")
+        self._fillAttribute(self._FirstPoint, None)
+        self._fillAttribute(self._SecondPoint, None)
+        self._fillAttribute(self._CylindricalFace, None)
+
+    def setPoints(self, p1, p2):
+        """Modify points attribute of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._fillAttribute(self._CreationMethod, "AxisByPointsCase")
+        self._fillAttribute(self._FirstPoint, p1)
+        self._fillAttribute(self._SecondPoint, p2)
+        pass
+
+    def setCylindricalFace(self, face):
+        """Modify CylindricalFace attribute of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._fillAttribute(self._CreationMethod, "AxisByCylindricalFaceCase")
+        self._fillAttribute(self._CylindricalFace, face)
+        pass
diff --git a/src/PythonAPI/model/construction/plane.py b/src/PythonAPI/model/construction/plane.py
new file mode 100644 (file)
index 0000000..e92a1e6
--- /dev/null
@@ -0,0 +1,96 @@
+"""Plane Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def addPlane(part, *args):
+    """Add a Plane feature to the Part and return Plane.
+
+    Pass all args to Plane __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("Plane")
+    return Plane(feature, *args)
+
+
+class Plane(Interface):
+    """Interface class for Plane feature.
+
+    Plane(feature) -> feature interface without initialization
+    Plane(feature, face, distance) ->
+        feature interface initialized from arguments:
+        - face -- planeFace
+        - distance -- distance
+    Plane(feature, a, b, c, d) ->
+        feature interface initialized from arguments:
+        - A, B, C, D -- GeneralEquation parameters
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Plane")
+
+        self._CreationMethod = self._feature.data().string("CreationMethod")
+        self._plane_face = self._feature.data().selection("planeFace")
+        self._distance = self._feature.data().real("distance")
+        self._a = self._feature.data().real("A")
+        self._b = self._feature.data().real("B")
+        self._c = self._feature.data().real("C")
+        self._d = self._feature.data().real("D")
+
+        assert(self._CreationMethod)
+        assert(self._plane_face)
+        assert(self._distance)
+        assert(self._a)
+        assert(self._b)
+        assert(self._c)
+        assert(self._d)
+
+        if not args:
+            return
+
+        assert(len(args) in (2, 4))
+        if len(args) == 2:
+            self.setFaceAndDistance(*args)
+        elif len(args) == 4:
+            self.setGeneralEquation(*args)
+
+        self.execute()
+        pass
+
+    def __clear(self):
+        self._fillAttribute(self._CreationMethod, "PlaneByFaceAndDistance")
+        self._fillAttribute(self._plane_face, None)
+        self._fillAttribute(self._distance, 0)
+        self._fillAttribute(self._a, 0)
+        self._fillAttribute(self._b, 0)
+        self._fillAttribute(self._c, 0)
+        self._fillAttribute(self._d, 0)
+
+    def setFaceAndDistance(self, face, distance):
+        """Modify face and distance attribute of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._fillAttribute(self._CreationMethod, "PlaneByFaceAndDistance")
+        self._fillAttribute(self._plane_face, face)
+        self._fillAttribute(self._distance, distance)
+        pass
+
+    def setGeneralEquation(self, a, b, c, d):
+        """Modify GeneralEquation parameters of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._fillAttribute(self._CreationMethod, "PlaneByGeneralEquation")
+        self._fillAttribute(self._a, a)
+        self._fillAttribute(self._b, b)
+        self._fillAttribute(self._c, c)
+        self._fillAttribute(self._d, d)
+        pass
diff --git a/src/PythonAPI/model/construction/point.py b/src/PythonAPI/model/construction/point.py
new file mode 100644 (file)
index 0000000..b7ef7d7
--- /dev/null
@@ -0,0 +1,58 @@
+"""Point Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def addPoint(part, *args):
+    """Add an Point feature to the Part and return Point.
+
+    Pass all args to Point __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("Point")
+    return Point(feature, *args)
+
+
+class Point(Interface):
+    """Interface class for Point feature.
+
+    Point(feature) -> feature interface without initialization
+    Point(feature, x, y, z) ->
+        feature interface initialized from arguments:
+        - x, y, z -- coordinates for the point
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Point")
+
+        self._x = self._feature.data().real("x")
+        self._y = self._feature.data().real("y")
+        self._z = self._feature.data().real("z")
+
+        assert(self._x)
+        assert(self._y)
+        assert(self._z)
+
+        if not args:
+            return
+
+        assert(len(args) == 3)
+        self.setPoint(*args)
+
+        self.execute()
+        pass
+
+    def setPoint(self, x, y, z):
+        """Modify base attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._x, x)
+        self._fillAttribute(self._y, y)
+        self._fillAttribute(self._z, z)
+        pass
diff --git a/src/PythonAPI/model/errors.py b/src/PythonAPI/model/errors.py
new file mode 100644 (file)
index 0000000..e10ec92
--- /dev/null
@@ -0,0 +1,22 @@
+# Package exceptions
+
+class ModelError(Exception):
+    """Base class for exceptions in this package."""
+    pass
+
+class WrongNumberOfArguments(ModelError):
+    """Exception raised when a wrong number of arguments is given."""
+    pass
+
+class FeatureInputInvalid(ModelError):
+    """Exception raised if a feature input is invalid."""
+    pass
+
+    #Attributes:
+        #expr -- input expression in which the error occurred
+        #msg  -- explanation of the error
+    #"""
+
+    #def __init__(self, expr, msg):
+        #self.expr = expr
+        #self.msg = msg
diff --git a/src/PythonAPI/model/exchange/__init__.py b/src/PythonAPI/model/exchange/__init__.py
new file mode 100644 (file)
index 0000000..71b17bb
--- /dev/null
@@ -0,0 +1,4 @@
+"""Package for Exchange plugin for the Parametric Geometry API of the Modeler.
+"""
+
+from exchange import addImport, exportToFile
\ No newline at end of file
diff --git a/src/PythonAPI/model/exchange/exchange.py b/src/PythonAPI/model/exchange/exchange.py
new file mode 100644 (file)
index 0000000..67d1de3
--- /dev/null
@@ -0,0 +1,122 @@
+"""Import Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def addImport(part, *args):
+    """Add an Import feature to the Part and return Import.
+
+    Pass all args to Import __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("Import")
+    return Import(feature, *args)
+
+
+class Import(Interface):
+    """Interface class for Import feature.
+
+    Import(feature) -> feature interface without initialization
+    Import(feature, file_path) ->
+        feature interface initialized from arguments:
+        - file_path -- path to the imported file
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Import")
+
+        self._file_path = self._feature.data().string("file_path")
+
+        assert(self._file_path)
+
+        if not args:
+            return
+
+        assert(len(args) == 1)
+        self.setFilePath(args[0])
+
+        self.execute()
+        pass
+
+    def setFilePath(self, file_path):
+        """Modify file path attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._file_path, file_path)
+        pass
+
+
+def exportToFile(part, *args):
+    """Add an Export feature to the Part and return Export.
+
+    Pass all args to Export __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("Export")
+    return Export(feature, *args)
+
+
+class Export(Interface):
+    """Interface class for Export feature.
+
+    Export(feature) -> feature interface without initialization
+    Export(feature, file_path, file_format, selection_list) ->
+        feature interface initialized from arguments:
+        - file_path -- path to the exported file
+        - file_format -- format of to the exported file
+        - selection_list -- objects to export
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Export")
+
+        self._file_path = self._feature.data().string("file_path")
+        self._file_format = self._feature.data().string("file_format")
+        self._objects = self._feature.data().selectionList("selection_list")
+
+        assert(self._file_path)
+        assert(self._file_format)
+        assert(self._objects)
+
+        if not args:
+            return
+
+        assert(len(args) == 3)
+        self.setFilePath(args[0])
+        self.setFileFormat(args[1])
+        self.setObjects(args[2])
+
+        self.execute()
+        pass
+
+    def setFilePath(self, file_path):
+        """Modify file path attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._file_path, file_path)
+        pass
+
+    def setFileFormat(self, file_format):
+        """Modify file path attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._file_format, file_format)
+        pass
+
+    def setObjects(self, objects):
+        """Modify file path attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._objects, object)
+        pass
diff --git a/src/PythonAPI/model/features/__init__.py b/src/PythonAPI/model/features/__init__.py
new file mode 100644 (file)
index 0000000..108d089
--- /dev/null
@@ -0,0 +1,20 @@
+"""Package for Features plugin for the Parametric Geometry API of the Modeler.
+"""
+
+from boolean import addAddition, addSubtraction, addIntersection
+
+from partition import addPartition
+
+from extrusion import addExtrusion
+from extrusion_boolean import addExtrusionCut, addExtrusionFuse
+from extrusion_sketch import addExtrusionSketch
+
+from revolution import addRevolution
+from revolution_boolean import addRevolutionCut, addRevolutionFuse
+from revolution_sketch import addRevolutionSketch
+
+from placement import addPlacement
+from rotation import addRotation
+from translation import addTranslation
+
+from group import addGroup
diff --git a/src/PythonAPI/model/features/boolean.py b/src/PythonAPI/model/features/boolean.py
new file mode 100644 (file)
index 0000000..89ce1fd
--- /dev/null
@@ -0,0 +1,96 @@
+"""Boolean operations Interface
+Author: Daniel Brunier-Coulin
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from ModelAPI    import *
+from GeomAlgoAPI import *
+
+
+from model.roots import Interface
+
+
+def addAddition(part, *args):
+    """Inserts an addition to the given Part and executes the operation.
+    This operation adds tool to the given object.
+    """
+    assert(args)
+    object, tool = args
+    feature = part.addFeature("Boolean")
+    return Boolean(feature, object, tool, GeomAlgoAPI_Boolean.BOOL_FUSE)
+
+
+def addSubtraction(part, *args):
+    """Inserts a subtraction to the given Part and executes the operation.
+    This operation subtracts tool to the given object.
+    """
+    assert(args)
+    object, tool = args
+    feature = part.addFeature("Boolean")
+    return Boolean(feature, object, tool, GeomAlgoAPI_Boolean.BOOL_CUT)
+
+
+def addIntersection(part, *args):
+    """Inserts an intersection to the given Part and executes the operation.
+    This operation intersects tool to the given object.
+    """
+    assert(args)
+    object, tool = args
+    feature = part.addFeature("Boolean")
+    return Boolean(feature, object, tool, GeomAlgoAPI_Boolean.BOOL_COMMON)
+
+
+class Boolean(Interface):
+    """Interface class for Boolean features.
+
+    Boolean(feature) -> feature interface without initialization
+    Boolean(feature, main_objects, tool_objects, bool_type) ->
+        feature interface initialized from arguments
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Boolean")
+
+        self._main_objects = self._feature.selectionList("main_objects")
+        self._tool_objects = self._feature.selectionList("tool_objects")
+        self._bool_type = self._feature.integer("bool_type")
+
+        assert(self._main_objects)
+        assert(self._tool_objects)
+        assert(self._bool_type)
+
+        if not args:
+            return
+
+        assert(len(args) == 3)
+        main_objects, tool_objects, bool_type = args
+
+        self.setMainObjects(main_objects)
+        self.setToolObjects(tool_objects)
+        self.setBoolType(bool_type)
+
+        self.execute()
+        pass
+
+    def setMainObjects(self, main_objects):
+        """F.setMainObjects(iterable) -- modify main_objects attribute"""
+        self._fillAttribute(self._main_objects, main_objects)
+        pass
+
+    def setToolObjects(self, tool_objects):
+        """F.setToolObjects(iterable) -- modify tool_objects attribute"""
+        self._fillAttribute(self._tool_objects, tool_objects)
+        pass
+
+    def setBoolType(self, bool_type):
+        """F.setBoolType(integer) -- modify bool_type attribute.
+
+        Available types:
+        - GeomAlgoAPI_Boolean.BOOL_FUSE
+        - GeomAlgoAPI_Boolean.BOOL_CUT
+        - GeomAlgoAPI_Boolean.BOOL_COMMON
+        """
+        self._fillAttribute(self._bool_type, bool_type)
+        pass
diff --git a/src/PythonAPI/model/features/extrusion.py b/src/PythonAPI/model/features/extrusion.py
new file mode 100644 (file)
index 0000000..1ecccf9
--- /dev/null
@@ -0,0 +1,144 @@
+"""Extrusion Interface
+Author: Daniel Brunier-Coulin with contribution by Mikhail Ponikarov
+        and Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+from model import Selection
+
+def addExtrusion(part, *args):
+    """Add an Extrusion feature to the Part and return Extrusion.
+
+    Pass all args to Extrusion __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("Extrusion")
+    return Extrusion(feature, *args)
+
+
+class Extrusion(Interface):
+    """Interface class for Extrusion feature.
+
+    Extrusion(feature) -> feature interface without initialization
+    Extrusion(feature, base, size) ->
+        feature interface initialized from arguments:
+        - base -- name, sketch or list of names and sketches
+        - size -- if positive -> to_size, if negative -> from_size
+    Extrusion(feature, base, to_size, from_size) ->
+        feature interface initialized from arguments:
+        - base -- name, sketch or list of names and sketches
+        - to_size -- upper size
+        - from_size -- lower size
+    Extrusion(feature, base, to_object, to_offset, from_object, from_offset) ->
+        feature interface initialized from arguments:
+        - base -- name, sketch or list of names and sketches
+        - to_object -- upper object (plane)
+        - to_offset -- offset from upper object
+        - from_object -- lower object (plane)
+        - from_offset -- offset from lower object
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Extrusion")
+
+        self._base = self._feature.data().selectionList("base")
+        self._CreationMethod = self._feature.string("CreationMethod")
+        self._to_size = self._feature.data().real("to_size")
+        self._from_size = self._feature.data().real("from_size")
+        self._to_object = self._feature.data().selection("to_object")
+        self._to_offset = self._feature.data().real("to_offset")
+        self._from_object = self._feature.data().selection("from_object")
+        self._from_offset = self._feature.data().real("from_offset")
+
+        assert(self._base)
+        assert(self._CreationMethod)
+        assert(self._to_size)
+        assert(self._from_size)
+        assert(self._to_object)
+        assert(self._to_offset)
+        assert(self._from_object)
+        assert(self._from_offset)
+
+        if not args:
+            return
+
+        assert(len(args) in (2, 3, 5))
+        base = args[0]
+        args = args[1:]
+
+        self.setBase(base)
+
+        if len(args) == 4:
+            self.setPlanesAndOffsets(*args)
+        elif len(args) == 2:
+            self.setSizes(*args)
+        elif len(args) == 1:
+            self.setSize(args[0])
+
+        self.execute()
+        pass
+
+    def __clear(self):
+        self._CreationMethod.setValue("BySizes")
+        self._fillAttribute(self._to_size, 0)
+        self._fillAttribute(self._from_size, 0)
+        self._fillAttribute(self._to_object, None)
+        self._fillAttribute(self._to_offset, 0)
+        self._fillAttribute(self._from_object, None)
+        self._fillAttribute(self._from_offset, 0)
+        pass
+
+    def setBase(self, base):
+        """Modify base attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._base, base)
+        pass
+
+    def setSizes(self, to_size, from_size):
+        """Modify the to_size, from_size attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._fillAttribute(self._CreationMethod, "BySizes")
+        self._fillAttribute(self._to_size, to_size)
+        self._fillAttribute(self._from_size, from_size)
+        pass
+
+    def setSize(self, size):
+        """Modify the size of the feature.
+
+        If size is positive then initialize to_size with size.
+        If size is negative then initialize from_size with -size.
+        """
+        to_size, from_size = 0, 0
+        if size >= 0:
+            to_size = size
+        else:
+            from_size = -size
+
+        self.setSizes(to_size, from_size)
+        pass
+
+    def setPlanesAndOffsets(self, to_object, to_offset,
+                            from_object, from_offset):
+        """Modify planes and offsets attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._CreationMethod.setValue("ByPlanesAndOffsets")
+        self._fillAttribute(self._to_object, to_object)
+        self._fillAttribute(self._to_offset, to_offset)
+        self._fillAttribute(self._from_object, from_object)
+        self._fillAttribute(self._from_offset, from_offset)
+        pass
+
+    def result(self):
+        """F.result() -> list of Selection objects"""
+        return [Selection(result, result.shape()) for result in (self.firstResult(),)]
diff --git a/src/PythonAPI/model/features/extrusion_boolean.py b/src/PythonAPI/model/features/extrusion_boolean.py
new file mode 100644 (file)
index 0000000..810a8a7
--- /dev/null
@@ -0,0 +1,125 @@
+"""ExtrusionCut and ExtrusionFuse  Interfaces
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from .roots import CompositeBoolean
+
+
+def addExtrusionCut(part, *args):
+    """Add an ExtrusionCut feature to the Part and return ExtrusionBoolean.
+
+    Pass all args to Extrusion __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("ExtrusionCut")
+    return ExtrusionBoolean(feature, *args)
+
+def addExtrusionFuse(part, *args):
+    """Add an ExtrusionFuse feature to the Part and return ExtrusionBoolean.
+
+    Pass all args to Extrusion __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("ExtrusionFuse")
+    return ExtrusionBoolean(feature, *args)
+
+
+class ExtrusionBoolean(CompositeBoolean):
+    """Interface class for ExtrusionBoolean features.
+
+    Supported features:
+    - ExtrusionCut
+    - ExtrusionFuse
+
+    ExtrusionBoolean(feature) -> feature interface without initialization
+    ExtrusionBoolean(feature,
+                     sketch, sketch_selection, boolean_objects,
+                     to_size, from_size) ->
+        feature interface initialized from arguments:
+        - sketch
+        - sketch_selection
+        - boolean_objects
+        - to_size
+        - from_size
+    ExtrusionBoolean(feature,
+                     sketch, sketch_selection, boolean_objects,
+                     to_object, to_offset, from_object, from_offset) ->
+        feature interface initialized from arguments:
+        - sketch
+        - sketch_selection
+        - boolean_objects
+        - to_object
+        - to_offset
+        - from_object
+        - from_offset
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        CompositeBoolean.__init__(self, feature, *args[:3])
+        args = args[3:]
+
+        self._CreationMethod = self._feature.string("CreationMethod")
+        self._to_size = self._feature.data().real("to_size")
+        self._from_size = self._feature.data().real("from_size")
+        self._to_object = self._feature.data().selection("to_object")
+        self._to_offset = self._feature.data().real("to_offset")
+        self._from_object = self._feature.data().selection("from_object")
+        self._from_offset = self._feature.data().real("from_offset")
+
+        assert(self._CreationMethod)
+        assert(self._to_size)
+        assert(self._from_size)
+        assert(self._to_object)
+        assert(self._to_offset)
+        assert(self._from_object)
+        assert(self._from_offset)
+
+        if not args:
+            return
+
+        assert(len(args) in (2, 4))
+        if len(args) == 4:
+            self.setPlanesAndOffsets(*args)
+        elif len(args) == 2:
+            self.setSizes(*args)
+
+        self.execute()
+        pass
+
+    def __clear(self):
+        self._CreationMethod.setValue("BySizes")
+        self._fillAttribute(self._to_size, 0)
+        self._fillAttribute(self._from_size, 0)
+        self._fillAttribute(self._to_object, None)
+        self._fillAttribute(self._to_offset, 0)
+        self._fillAttribute(self._from_object, None)
+        self._fillAttribute(self._from_offset, 0)
+        pass
+
+    def setSizes(self, to_size, from_size):
+        """Modify the to_size, from_size attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._CreationMethod.setValue("BySizes")
+        self._fillAttribute(self._to_size, to_size)
+        self._fillAttribute(self._from_size, from_size)
+        pass
+
+    def setPlanesAndOffsets(self, to_object, to_offset,
+                            from_object, from_offset):
+        """Modify planes and offsets attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._CreationMethod.setValue("ByPlanesAndOffsets")
+        self._fillAttribute(self._to_object, to_object)
+        self._fillAttribute(self._to_offset, to_offset)
+        self._fillAttribute(self._from_object, from_object)
+        self._fillAttribute(self._from_offset, from_offset)
+        pass
+
diff --git a/src/PythonAPI/model/features/extrusion_sketch.py b/src/PythonAPI/model/features/extrusion_sketch.py
new file mode 100644 (file)
index 0000000..627a1c5
--- /dev/null
@@ -0,0 +1,109 @@
+"""ExtrusionSketch  Interfaces
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from .roots import CompositeSketch
+
+
+def addExtrusionSketch(part, *args):
+    """Add an ExtrusionSketch feature to the Part and return ExtrusionSketch.
+
+    Pass all args to ExtrusionSketch __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("ExtrusionSketch")
+    return ExtrusionSketch(feature, *args)
+
+
+class ExtrusionSketch(CompositeSketch):
+    """Interface class for ExtrusionSketch feature.
+
+    ExtrusionSketch(feature) -> feature interface without initialization
+    ExtrusionSketch(feature,
+                    sketch, sketch_selection,
+                    to_size, from_size) ->
+        feature interface initialized from arguments:
+        - sketch
+        - sketch_selection
+        - to_size
+        - from_size
+    ExtrusionSketch(feature,
+                    sketch, sketch_selection,
+                    to_object, to_offset, from_object, from_offset) ->
+        feature interface initialized from arguments:
+        - sketch
+        - sketch_selection
+        - to_object
+        - to_offset
+        - from_object
+        - from_offset
+    """
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        CompositeSketch.__init__(self, feature, *args[:2])
+        args = args[2:]
+
+        self._CreationMethod = self._feature.string("CreationMethod")
+        self._to_size = self._feature.data().real("to_size")
+        self._from_size = self._feature.data().real("from_size")
+        self._to_object = self._feature.data().selection("to_object")
+        self._to_offset = self._feature.data().real("to_offset")
+        self._from_object = self._feature.data().selection("from_object")
+        self._from_offset = self._feature.data().real("from_offset")
+
+        assert(self._CreationMethod)
+        assert(self._to_size)
+        assert(self._from_size)
+        assert(self._to_object)
+        assert(self._to_offset)
+        assert(self._from_object)
+        assert(self._from_offset)
+
+        if not args:
+            return
+
+        assert(len(args) in (2, 4))
+        if len(args) == 4:
+            self.setPlanesAndOffsets(*args)
+        elif len(args) == 2:
+            self.setSizes(*args)
+
+        self.execute()
+        pass
+
+    def __clear(self):
+        self._CreationMethod.setValue("BySizes")
+        self._fillAttribute(self._to_size, 0)
+        self._fillAttribute(self._from_size, 0)
+        self._fillAttribute(self._to_object, None)
+        self._fillAttribute(self._to_offset, 0)
+        self._fillAttribute(self._from_object, None)
+        self._fillAttribute(self._from_offset, 0)
+        pass
+
+    def setSizes(self, to_size, from_size):
+        """Modify the to_size, from_size attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._CreationMethod.setValue("BySizes")
+        self._fillAttribute(self._to_size, to_size)
+        self._fillAttribute(self._from_size, from_size)
+        pass
+
+    def setPlanesAndOffsets(self, to_object, to_offset,
+                            from_object, from_offset):
+        """Modify planes and offsets attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._CreationMethod.setValue("ByPlanesAndOffsets")
+        self._fillAttribute(self._to_object, to_object)
+        self._fillAttribute(self._to_offset, to_offset)
+        self._fillAttribute(self._from_object, from_object)
+        self._fillAttribute(self._from_offset, from_offset)
+        pass
+
diff --git a/src/PythonAPI/model/features/group.py b/src/PythonAPI/model/features/group.py
new file mode 100644 (file)
index 0000000..7e098d5
--- /dev/null
@@ -0,0 +1,52 @@
+"""Group Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def addGroup(part, *args):
+    """Add an Group feature to the Part and return Group.
+
+    Pass all args to Group __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("Group")
+    return Group(feature, *args)
+
+
+class Group(Interface):
+    """Interface class for Group feature.
+
+    Group(feature) -> feature interface without initialization
+    Group(feature, group_list) ->
+        feature interface initialized from arguments:
+        - group_list
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Group")
+
+        self._group_list = self._feature.data().selectionList("group_list")
+
+        assert(self._group_list)
+
+        if not args:
+            return
+
+        assert(len(args) == 1)
+        self.setGroupList(args[0])
+
+        self.execute()
+        pass
+
+    def setGroupList(self, main_objects):
+        """Modify group_list attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._group_list, group_list)
+        pass
diff --git a/src/PythonAPI/model/features/partition.py b/src/PythonAPI/model/features/partition.py
new file mode 100644 (file)
index 0000000..fb9056e
--- /dev/null
@@ -0,0 +1,78 @@
+"""Partition Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def addPartition(part, *args):
+    """Add an Partition feature to the Part and return Partition.
+
+    Pass all args to Partition __init__ function.
+    """
+    assert(len(args) > 0 and args[0] is not None)
+    feature = part.addFeature("Partition")
+    return Partition(feature, *args)
+
+
+class Partition(Interface):
+    """Interface class for Partition feature.
+
+    Partition(feature) -> feature interface without initialization
+    Partition(feature, main_objects, tool_objects, partition_combine) ->
+        feature interface initialized from arguments:
+        - main_objects -- list of solids
+        - tool_objects -- list of solids
+        - partition_combine -- boolean value
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Partition")
+
+        self._main_objects = self._feature.data().selectionList("main_objects")
+        self._tool_objects = self._feature.data().selectionList("tool_objects")
+        self._partition_combine = self._feature.data().boolean("partition_combine")
+
+        assert(self._main_objects)
+        assert(self._tool_objects)
+        assert(self._partition_combine)
+
+        if not args:
+            return
+
+        assert(len(args) == 3)
+        main_objects, tool_objects, partition_combine = args
+
+        self.setMainObjects(main_objects)
+        self.setToolObjects(tool_objects)
+        self.setPartitionCombine(partition_combine)
+
+        self.execute()
+        pass
+
+    def setMainObjects(self, main_objects):
+        """Modify base attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._main_objects, main_objects)
+        pass
+
+    def setToolObjects(self, tool_objects):
+        """Modify the to_size, from_size attributes of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._tool_objects, tool_objects)
+        pass
+
+    def setPartitionCombine(self, partition_combine):
+        """Modify planes and offsets attributes of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._partition_combine, partition_combine)
+        pass
diff --git a/src/PythonAPI/model/features/placement.py b/src/PythonAPI/model/features/placement.py
new file mode 100644 (file)
index 0000000..cd9e058
--- /dev/null
@@ -0,0 +1,101 @@
+"""Placement Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def addPlacement(part, *args):
+    """Add an Placement feature to the Part and return Placement.
+
+    Pass all args to Placement __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("Placement")
+    return Placement(feature, *args)
+
+
+class Placement(Interface):
+    """Interface class for Placement feature.
+
+    Placement(feature) -> feature interface without initialization
+    Placement(feature, objects_list, start_shape, end_shape,
+              reverse_direction, centering) ->
+        feature interface initialized from arguments:
+        - objects_list
+        - start_shape
+        - end_shape
+        - reverse_direction
+        - centering
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Placement")
+
+        self._objects_list = self._feature.data().selectionList("placement_objects_list")
+        self._start_shape = self._feature.data().selection("placement_start_shape")
+        self._end_shape = self._feature.data().selection("placement_end_shape")
+        self._reverse_direction = self._feature.data().boolean("placement_reverse_direction")
+        self._centering = self._feature.data().boolean("placement_centering")
+
+        assert(self._objects_list)
+        assert(self._start_shape)
+        assert(self._end_shape)
+        assert(self._reverse_direction)
+        assert(self._centering)
+
+        if not args:
+            return
+
+        assert(len(args) == 5)
+        self.setObjectList(args[0])
+        self.setStartShape(args[1])
+        self.setEndShape(args[2])
+        self.setReverseDirection(args[3])
+        self.setCentering(args[4])
+
+        self.execute()
+        pass
+
+    def setObjectList(self, objects_list):
+        """Modify placement_objects_list attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._objects_list, objects_list)
+        pass
+
+    def setStartShape(self, start_shape):
+        """Modify start_shape attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._start_shape, start_shape)
+        pass
+
+    def setEndShape(self, end_shape):
+        """Modify end_shape attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._end_shape, end_shape)
+        pass
+
+    def setReverseDirection(self, reverse_direction):
+        """Modify reverse_direction attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._reverse_direction, reverse_direction)
+        pass
+
+    def setCentering(self, centering):
+        """Modify centering attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._centering, centering)
+        pass
diff --git a/src/PythonAPI/model/features/revolution.py b/src/PythonAPI/model/features/revolution.py
new file mode 100644 (file)
index 0000000..d5985b3
--- /dev/null
@@ -0,0 +1,133 @@
+"""Revolution Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def addRevolution(part, *args):
+    """Add an Revolution feature to the Part and return Revolution.
+
+    Pass all args to Revolution __init__ function.
+    """
+    assert(len(args) > 0 and args[0] is not None)
+    feature = part.addFeature("Revolution")
+    return Revolution(feature, *args)
+
+
+class Revolution(Interface):
+    """Interface class for Revolution features.
+
+    Revolution(feature) -> feature interface without initialization
+    Revolution(feature, base, axis_object, to_angle, from_angle) ->
+        feature interface initialized from arguments:
+        - base -- name, sketch or list of names and sketches
+        - axis_object -- name, edge for axis
+        - to_angle -- upper angle
+        - from_angle -- lower angle
+    Revolution(feature, base, axis_object,
+               to_object, to_offset, from_object, from_offset) ->
+        feature interface initialized from arguments:
+        - base -- name, sketch or list of names and sketches
+        - axis_object -- name, edge for axis
+        - to_object -- upper object (plane)
+        - to_offset -- offset from upper object
+        - from_object -- lower object (plane)
+        - from_offset -- offset from lower object
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Revolution")
+
+        self._base = self._feature.data().selectionList("base")
+        self._axis_object = self._feature.data().selection("axis_object")
+        self._CreationMethod = self._feature.string("CreationMethod")
+        self._to_angle = self._feature.data().real("to_angle")
+        self._from_angle = self._feature.data().real("from_angle")
+        self._to_object = self._feature.data().selection("to_object")
+        self._to_offset = self._feature.data().real("to_offset")
+        self._from_object = self._feature.data().selection("from_object")
+        self._from_offset = self._feature.data().real("from_offset")
+
+        assert(self._base)
+        assert(self._axis_object)
+        assert(self._CreationMethod)
+        assert(self._to_angle)
+        assert(self._from_angle)
+        assert(self._to_object)
+        assert(self._to_offset)
+        assert(self._from_object)
+        assert(self._from_offset)
+
+        if not args:
+            return
+
+        assert(len(args) in (4, 6))
+
+        base, axis_object = args[:2]
+        args = args[2:]
+
+        self.setBase(base)
+        self.setAxisObject(axis_object)
+
+        if len(args) == 4:
+            self.setPlanesAndOffsets(*args)
+        elif len(args) == 2:
+            self.setAngles(*args)
+
+        self.execute()
+        pass
+
+    def __clear(self):
+        self._CreationMethod.setValue("ByAngles")
+        self._fillAttribute(self._to_angle, 0)
+        self._fillAttribute(self._from_angle, 0)
+        self._fillAttribute(self._to_object, None)
+        self._fillAttribute(self._to_offset, 0)
+        self._fillAttribute(self._from_object, None)
+        self._fillAttribute(self._from_offset, 0)
+        pass
+
+    def setBase(self, base):
+        """Modify base attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._base, base)
+        pass
+
+    def setAxisObject(self, axis_object):
+        """Modify axis_object attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._axis_object, axis_object)
+        pass
+
+    def setAngles(self, to_angle, from_angle):
+        """Modify the to_angle, from_angle attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._CreationMethod.setValue("ByAngles")
+        self._fillAttribute(self._to_angle, to_angle)
+        self._fillAttribute(self._from_angle, from_angle)
+        pass
+
+    def setPlanesAndOffsets(self, to_object, to_offset,
+                            from_object, from_offset):
+        """Modify planes and offsets attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._CreationMethod.setValue("ByPlanesAndOffsets")
+        self._fillAttribute(self._to_object, to_object)
+        self._fillAttribute(self._to_offset, to_offset)
+        self._fillAttribute(self._from_object, from_object)
+        self._fillAttribute(self._from_offset, from_offset)
+        pass
diff --git a/src/PythonAPI/model/features/revolution_boolean.py b/src/PythonAPI/model/features/revolution_boolean.py
new file mode 100644 (file)
index 0000000..61361de
--- /dev/null
@@ -0,0 +1,140 @@
+"""RevolutionCut and RevolutionFuse Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from .roots import CompositeBoolean
+
+
+def addRevolutionCut(part, *args):
+    """Add an RevolutionCut feature to the Part and return RevolutionBoolean.
+
+    Pass all args to RevolutionCut __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("RevolutionCut")
+    return RevolutionBoolean(feature, *args)
+
+def addRevolutionFuse(part, *args):
+    """Add an RevolutionFuse feature to the Part and return RevolutionBoolean.
+
+    Pass all args to RevolutionFuse __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("RevolutionFuse")
+    return RevolutionBoolean(feature, *args)
+
+
+class RevolutionBoolean(CompositeBoolean):
+    """Interface class for RevolutionBoolean features.
+
+    Supported features:
+    - RevolutionCut
+    - RevolutionFuse
+
+    RevolutionBoolean(feature) -> feature interface without initialization
+    RevolutionBoolean(feature,
+                      sketch, sketch_selection, boolean_objects,
+                      to_angle, from_angle) ->
+        feature interface initialized from arguments:
+        - sketch
+        - sketch_selection
+        - boolean_objects
+        - to_angle
+        - from_angle
+    RevolutionBoolean(feature,
+                      sketch, sketch_selection, boolean_objects,
+                      to_object, to_offset, from_object, from_offset) ->
+        feature interface initialized from arguments:
+        - sketch
+        - sketch_selection
+        - boolean_objects
+        - to_object
+        - to_offset
+        - from_object
+        - from_offset
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        CompositeBoolean.__init__(self, feature, *args[:3])
+        args = args[3:]
+
+        self._axis_object = self._feature.data().selection("axis_object")
+        self._CreationMethod = self._feature.string("CreationMethod")
+        self._to_angle = self._feature.data().real("to_angle")
+        self._from_angle = self._feature.data().real("from_angle")
+        self._to_object = self._feature.data().selection("to_object")
+        self._to_offset = self._feature.data().real("to_offset")
+        self._from_object = self._feature.data().selection("from_object")
+        self._from_offset = self._feature.data().real("from_offset")
+
+        assert(self._axis_object)
+        assert(self._CreationMethod)
+        assert(self._to_angle)
+        assert(self._from_angle)
+        assert(self._to_object)
+        assert(self._to_offset)
+        assert(self._from_object)
+        assert(self._from_offset)
+
+        if not args:
+            return
+
+        assert(len(args) in (3, 5))
+        axis_object = args[0]
+        args = args[1:]
+
+        self.setAxisObject(axis_object)
+
+        if len(args) == 4:
+            self.setPlanesAndOffsets(*args)
+        elif len(args) == 2:
+            self.setAngles(*args)
+
+        self.execute()
+        pass
+
+    def __clear(self):
+        self._CreationMethod.setValue("ByAngles")
+        self._fillAttribute(self._to_angle, 0)
+        self._fillAttribute(self._from_angle, 0)
+        self._fillAttribute(self._to_object, None)
+        self._fillAttribute(self._to_offset, 0)
+        self._fillAttribute(self._from_object, None)
+        self._fillAttribute(self._from_offset, 0)
+        pass
+
+    def setAxisObject(self, axis_object):
+        """Modify axis_object attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._axis_object, axis_object)
+        pass
+
+    def setAngles(self, to_angle, from_angle):
+        """Modify the to_angle, from_angle attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._CreationMethod.setValue("ByAngles")
+        self._fillAttribute(self._to_angle, to_angle)
+        self._fillAttribute(self._from_angle, from_angle)
+        pass
+
+    def setPlanesAndOffsets(self, to_object, to_offset,
+                            from_object, from_offset):
+        """Modify planes and offsets attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._CreationMethod.setValue("ByPlanesAndOffsets")
+        self._fillAttribute(self._to_object, to_object)
+        self._fillAttribute(self._to_offset, to_offset)
+        self._fillAttribute(self._from_object, from_object)
+        self._fillAttribute(self._from_offset, from_offset)
+        pass
+
diff --git a/src/PythonAPI/model/features/revolution_sketch.py b/src/PythonAPI/model/features/revolution_sketch.py
new file mode 100644 (file)
index 0000000..c75d0c0
--- /dev/null
@@ -0,0 +1,125 @@
+"""RevolutionSketch Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from .roots import CompositeSketch
+
+
+def addRevolutionSketch(part, *args):
+    """Add an RevolutionSketch feature to the Part and return RevolutionSketch.
+
+    Pass all args to RevolutionSketch __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("RevolutionSketch")
+    return RevolutionSketch(feature, *args)
+
+
+class RevolutionSketch(CompositeSketch):
+    """Interface class for RevolutionSketch features.
+
+    RevolutionSketch(feature) -> feature interface without initialization
+    RevolutionSketch(feature,
+                     sketch, sketch_selection,
+                     to_angle, from_angle) ->
+        feature interface initialized from arguments:
+        - sketch
+        - sketch_selection
+        - to_angle
+        - from_angle
+    RevolutionSketch(feature,
+                     sketch, sketch_selection,
+                     to_object, to_offset, from_object, from_offset) ->
+        feature interface initialized from arguments:
+        - sketch
+        - sketch_selection
+        - to_object
+        - to_offset
+        - from_object
+        - from_offset
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        CompositeSketch.__init__(self, feature, *args[:2])
+        args = args[2:]
+
+        self._axis_object = self._feature.data().selection("axis_object")
+        self._CreationMethod = self._feature.string("CreationMethod")
+        self._to_angle = self._feature.data().real("to_angle")
+        self._from_angle = self._feature.data().real("from_angle")
+        self._to_object = self._feature.data().selection("to_object")
+        self._to_offset = self._feature.data().real("to_offset")
+        self._from_object = self._feature.data().selection("from_object")
+        self._from_offset = self._feature.data().real("from_offset")
+
+        assert(self._axis_object)
+        assert(self._CreationMethod)
+        assert(self._to_angle)
+        assert(self._from_angle)
+        assert(self._to_object)
+        assert(self._to_offset)
+        assert(self._from_object)
+        assert(self._from_offset)
+
+        if not args:
+            return
+
+        assert(len(args) in (3, 5))
+        axis_object = args[0]
+        args = args[1:]
+
+        self.setAxisObject(axis_object)
+
+        if len(args) == 4:
+            self.setPlanesAndOffsets(*args)
+        elif len(args) == 2:
+            self.setAngles(*args)
+
+        self.execute()
+        pass
+
+    def __clear(self):
+        self._CreationMethod.setValue("ByAngles")
+        self._fillAttribute(self._to_angle, 0)
+        self._fillAttribute(self._from_angle, 0)
+        self._fillAttribute(self._to_object, None)
+        self._fillAttribute(self._to_offset, 0)
+        self._fillAttribute(self._from_object, None)
+        self._fillAttribute(self._from_offset, 0)
+        pass
+
+    def setAxisObject(self, axis_object):
+        """Modify axis_object attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._axis_object, axis_object)
+        pass
+
+    def setAngles(self, to_angle, from_angle):
+        """Modify the to_angle, from_angle attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._CreationMethod.setValue("ByAngles")
+        self._fillAttribute(self._to_angle, to_angle)
+        self._fillAttribute(self._from_angle, from_angle)
+        pass
+
+    def setPlanesAndOffsets(self, to_object, to_offset,
+                            from_object, from_offset):
+        """Modify planes and offsets attributes of the feature.
+
+        See __init__.
+        """
+        self.__clear()
+        self._CreationMethod.setValue("ByPlanesAndOffsets")
+        self._fillAttribute(self._to_object, to_object)
+        self._fillAttribute(self._to_offset, to_offset)
+        self._fillAttribute(self._from_object, from_object)
+        self._fillAttribute(self._from_offset, from_offset)
+        pass
+
diff --git a/src/PythonAPI/model/features/roots.py b/src/PythonAPI/model/features/roots.py
new file mode 100644 (file)
index 0000000..2aeacfe
--- /dev/null
@@ -0,0 +1,94 @@
+
+from model.roots import Interface
+
+
+class CompositeBoolean(Interface):
+    """Interface class for CompositeBoolean features.
+
+    CompositeBoolean(feature) -> feature interface without initialization
+    CompositeBoolean(feature, sketch, sketch_selection, boolean_objects) ->
+        feature interface initialized from arguments:
+        - sketch
+        - sketch_selection
+        - boolean_objects
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+
+        self._sketch = self._feature.reference("sketch")
+        self._sketch_selection = self._feature.selection("sketch_selection")
+        self._boolean_objects = self._feature.selectionList("boolean_objects")
+
+        assert(self._sketch)
+        assert(self._sketch_selection)
+        assert(self._boolean_objects)
+
+        if not args:
+            return
+
+        assert(len(args) == 3)
+        sketch, sketch_selection, boolean_objects = args
+
+        self.setSketch(sketch)
+        self.setSketchSelection(sketch_selection)
+        self.setBooleanObjects(boolean_objects)
+        pass
+
+    def setSketch(self, sketch):
+        """Modify sketch attribute"""
+        self._fillAttribute(self._sketch, sketch)
+        pass
+
+    def setSketchSelection(self, sketch_selection):
+        """Modify sketch_selection attribute"""
+        self._fillAttribute(self._sketch_selection, sketch_selection)
+        pass
+
+    def setBooleanObjects(self, boolean_objects):
+        """Modify boolean_objects attribute"""
+        self._fillAttribute(self._boolean_objects, boolean_objects)
+        pass
+
+
+class CompositeSketch(Interface):
+    """Interface class for CompositeSketch features.
+
+    CompositeSketch(feature) -> feature interface without initialization
+    CompositeSketch(feature, sketch, sketch_selection) ->
+        feature interface initialized from arguments:
+        - sketch
+        - sketch_selection
+    """
+
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+
+        self._sketch = self._feature.reference("sketch")
+        self._sketch_selection = self._feature.selection("sketch_selection")
+
+        assert(self._sketch)
+        assert(self._sketch_selection)
+
+        if not args:
+            return
+
+        assert(len(args) == 2)
+        sketch, sketch_selection = args
+
+        self.setSketch(sketch)
+        self.setSketchSelection(sketch_selection)
+        pass
+
+    def setSketch(self, sketch):
+        """Modify sketch attribute"""
+        self._fillAttribute(self._sketch, sketch)
+        pass
+
+    def setSketchSelection(self, sketch_selection):
+        """Modify sketch_selection attribute"""
+        self._fillAttribute(self._sketch_selection, sketch_selection)
+        pass
diff --git a/src/PythonAPI/model/features/rotation.py b/src/PythonAPI/model/features/rotation.py
new file mode 100644 (file)
index 0000000..0a1cf9a
--- /dev/null
@@ -0,0 +1,76 @@
+"""Rotation Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def addRotation(part, *args):
+    """Add an Rotation feature to the Part and return Rotation.
+
+    Pass all args to Rotation __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("Rotation")
+    return Rotation(feature, *args)
+
+
+class Rotation(Interface):
+    """Interface class for Rotation features.
+
+    Rotation(feature) -> feature interface without initialization
+    Rotation(feature, main_objects, axis_object, angle) ->
+        feature interface initialized from arguments:
+        - main_objects
+        - axis_object
+        - angle
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Rotation")
+
+        self._main_objects = self._feature.data().selectionList("main_objects")
+        self._axis_object = self._feature.data().selection("axis_object")
+        self._angle = self._feature.data().real("angle")
+
+        assert(self._main_objects)
+        assert(self._axis_object)
+        assert(self._angle)
+
+        if not args:
+            return
+
+        assert(len(args) == 3)
+        self.setMainObjects(args[0])
+        self.setAxisObject(args[1])
+        self.setAngle(args[2])
+
+        self.execute()
+        pass
+
+    def setMainObjects(self, main_objects):
+        """Modify main_objects attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._main_objects, main_objects)
+        pass
+
+    def setAxisObject(self, axis_object):
+        """Modify axis_object attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._axis_object, axis_object)
+        pass
+
+    def setAngle(self, angle):
+        """Modify angle attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._angle, angle)
+        pass
diff --git a/src/PythonAPI/model/features/translation.py b/src/PythonAPI/model/features/translation.py
new file mode 100644 (file)
index 0000000..1a38689
--- /dev/null
@@ -0,0 +1,76 @@
+"""Translation Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def addTranslation(part, *args):
+    """Add an Translation feature to the Part and return Translation.
+
+    Pass all args to Translation __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("Translation")
+    return Translation(feature, *args)
+
+
+class Translation(Interface):
+    """Interface class for Translation features.
+
+    Translation(feature) -> feature interface without initialization
+    Translation(feature, main_objects, axis_object, distance) ->
+        feature interface initialized from arguments:
+        - main_objects
+        - axis_object
+        - distance
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Translation")
+
+        self._main_objects = self._feature.data().selectionList("main_objects")
+        self._axis_object = self._feature.data().selection("axis_object")
+        self._distance = self._feature.data().real("distance")
+
+        assert(self._main_objects)
+        assert(self._axis_object)
+        assert(self._distance)
+
+        if not args:
+            return
+
+        assert(len(args) == 3)
+        self.setMainObjects(args[0])
+        self.setAxisObject(args[1])
+        self.setDistance(args[2])
+
+        self.execute()
+        pass
+
+    def setMainObjects(self, main_objects):
+        """Modify main_objects attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._main_objects, main_objects)
+        pass
+
+    def setAxisObject(self, axis_object):
+        """Modify axis_object attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._axis_object, axis_object)
+        pass
+
+    def setDistance(self, distance):
+        """Modify distance attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._distance, distance)
+        pass
diff --git a/src/PythonAPI/model/parameter/__init__.py b/src/PythonAPI/model/parameter/__init__.py
new file mode 100644 (file)
index 0000000..44bde3f
--- /dev/null
@@ -0,0 +1,4 @@
+"""Package for Parameter plugin for the Parametric Geometry API of the Modeler.
+"""
+
+from parameter import addParameter
\ No newline at end of file
diff --git a/src/PythonAPI/model/parameter/parameter.py b/src/PythonAPI/model/parameter/parameter.py
new file mode 100644 (file)
index 0000000..a39810c
--- /dev/null
@@ -0,0 +1,64 @@
+"""Parameter Interface
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from model.roots import Interface
+
+
+def addParameter(part, *args):
+    """Add a Parameter feature to the Part and return Parameter.
+
+    Pass all args to Parameter __init__ function.
+    """
+    assert(args)
+    feature = part.addFeature("Parameter")
+    return Parameter(feature, *args)
+
+
+class Parameter(Interface):
+    """Interface class for Parameter feature.
+
+    Parameter(feature) -> feature interface without initialization
+    Parameter(feature, variable, expression) ->
+        feature interface initialized from arguments:
+        - variable -- variable name
+        - expression -- Python expression
+    """
+
+    def __init__(self, feature, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Parameter")
+
+        self._variable = self._feature.data().string("variable")
+        self._expression = self._feature.data().string("expression")
+
+        assert(self._variable)
+        assert(self._expression)
+
+        if not args:
+            return
+
+        assert(len(args) == 2)
+        self.setName(args[0])
+        self.setExpression(args[1])
+
+        self.execute()
+        pass
+
+    def setName(self, name):
+        """Modify variable name attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._name, name)
+        pass
+
+    def setExpression(self, expression):
+        """Modify expression attribute of the feature.
+
+        See __init__.
+        """
+        self._fillAttribute(self._expression, expression)
+        pass
diff --git a/src/PythonAPI/model/partset/__init__.py b/src/PythonAPI/model/partset/__init__.py
new file mode 100644 (file)
index 0000000..33eed0d
--- /dev/null
@@ -0,0 +1,4 @@
+"""Package for PartSet plugin for the Parametric Geometry API of the Modeler.
+"""
+
+from part import addPart, duplicatePart, removePart
\ No newline at end of file
diff --git a/src/PythonAPI/model/partset/part.py b/src/PythonAPI/model/partset/part.py
new file mode 100644 (file)
index 0000000..de956ea
--- /dev/null
@@ -0,0 +1,48 @@
+"""Part Feature Interface
+Author: Daniel Brunier-Coulin
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+import ModelAPI
+
+from model.roots import Interface
+
+
+def addPart(partset):
+    """Add a Part feature to the Part and return Part.
+
+    Pass all args to Part __init__ function.
+    """
+    feature = partset.addFeature("Part")
+    return Part(feature)
+
+def duplicatePart(part):
+    """Create a copy of the Part."""
+    feature = part.addFeature("Duplicate")
+    feature.execute()
+    return Part(feature)
+
+def removePart(part):
+    """Remove the Part."""
+    feature = part.addFeature("Remove")
+    feature.execute()
+
+
+class Part(Interface):
+    """Interface class for Part feature.
+
+    Part(feature) -> feature interface without initialization
+    """
+
+    def __init__(self, feature):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Part")
+
+        self.execute()
+        pass
+
+    def document(self):
+        """Returns the Part document created by this feature."""
+        result_part = ModelAPI.modelAPI_ResultPart(self._feature.firstResult())
+        return result_part.partDoc()
diff --git a/src/PythonAPI/model/roots.py b/src/PythonAPI/model/roots.py
new file mode 100644 (file)
index 0000000..29080e2
--- /dev/null
@@ -0,0 +1,103 @@
+"""Abstract root classes of user-defined Python features producing a Body
+Author: Daniel Brunier-Coulin
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+import ModelAPI
+
+from model import tools
+
+
+class Feature(ModelAPI.ModelAPI_Feature):
+    """Base class of user-defined Python features."""
+
+    def __init__(self):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        ModelAPI.ModelAPI_Feature.__init__(self)
+
+    def addRealInput(self, inputid):
+        """F.addRealInput(str) -- add real attribute"""
+        self.data().addAttribute(inputid,
+                                 ModelAPI.ModelAPI_AttributeDouble_typeId())
+
+    def getRealInput(self, inputid):
+        """F.getRealInput(str) -- get real value of the attribute"""
+        return self.data().real(inputid).value()
+
+    def addResult(self, result):
+        """F.addResult(ModelAPI_Result) -- add ModelAPI_Result shape as a result"""
+        shape = result.shape()
+        body = self.document().createBody(self.data())
+        body.store(shape)
+        self.setResult(body)
+
+
+class Interface():
+    """Base class of high level Python interfaces to features."""
+
+    def __init__(self, feature):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        self._feature = feature
+
+    def __getattr__(self, name):
+        """Process missing attributes.
+
+        Add get*() methods for access feature attributes.
+        """
+        if name.startswith("get"):
+            possible_names = [
+                "_" + name[3:],
+                "_" + tools.convert_to_underscore(name[3:]),
+                ]
+            for possible_name in possible_names:
+                if hasattr(self, possible_name):
+                    def getter():
+                        return getattr(self, possible_name)
+                    return getter
+
+        raise AttributeError()
+
+    def _fillAttribute(self, attribute, value):
+        """Fill ModelAPI_Attribute* with value."""
+        tools.fill_attribute(attribute, value)
+
+    def feature(self):
+        """Return ModelAPI_Feature."""
+        return self._feature
+
+    def getKind(self):
+        """Return the unique kind of the feature"""
+        return self._feature.getKind()
+
+    def results(self):
+        """Return current results of the feature"""
+        return self._feature.results()
+
+    def firstResult(self):
+        """Return the first result in the list of results"""
+        return self._feature.firstResult()
+
+    def lastResult(self):
+        """Return the result in the list of results"""
+        return self._feature.lastResult()
+
+    def setRealInput(self, inputid, value):
+        """I.setRealInput(str, float) -- set real value to the attribute"""
+        self._feature.data().real(inputid).setValue(value)
+
+    def areInputValid(self):
+        """I.areInputValid() -> True or False validation result"""
+        validators = ModelAPI.ModelAPI_Session.get().validators()
+        return validators.validate(self._feature)
+
+    def execute(self):
+        """I.execute() -- validate and execute the feature.
+
+        Raises RuntimeError if validation fails.
+        """
+        if self.areInputValid():
+            self._feature.execute()
+        else:
+            raise RuntimeError("Can not execute %s: %s" %
+                               (self._feature.getKind(), self._feature.error())
+                               )
diff --git a/src/PythonAPI/model/services.py b/src/PythonAPI/model/services.py
new file mode 100644 (file)
index 0000000..962087b
--- /dev/null
@@ -0,0 +1,89 @@
+"""General purpose Interface
+Author: Daniel Brunier-Coulin
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+import ModelAPI
+import GeomAPI
+
+import geom  # To be removed when gp_Ax3 will be Pythonized
+
+
+def moduleDocument ():
+    """Return the main document (the Partset) created or open from the Modeler.
+
+    This document is unique in the application session.
+    """
+    return ModelAPI.ModelAPI_Session.get().moduleDocument()
+
+
+def activeDocument ():
+    """Return the active document.
+
+    This document can be either the main application document (i.e. the Partset) or one of documents
+    referred to by the main document (a Part).
+    """
+    return ModelAPI.ModelAPI_Session.get().activeDocument()
+
+
+def defaultPlane (name):
+    """Return one of the three planes defined by the global coordinate system.
+
+    These planes are respectively referred to by name "XOY" (Z=0), "XOZ" (Y=0) or "YOZ" (X=0).
+    """
+    # Temporary implementation before the availability of default planes.
+    o = GeomAPI.GeomAPI_Pnt(0, 0, 0)
+    if   name == "XOY":
+        n = GeomAPI.GeomAPI_Dir(0, 0, 1)
+        x = GeomAPI.GeomAPI_Dir(1, 0, 0)
+    elif name == "XOZ":
+        n = GeomAPI.GeomAPI_Dir(0, 1, 0)
+        x = GeomAPI.GeomAPI_Dir(1, 0, 0)
+    elif name == "YOZ":
+        n = GeomAPI.GeomAPI_Dir(1, 0, 0)
+        x = GeomAPI.GeomAPI_Dir(0, 1, 0)
+
+    return geom.Ax3(o, n, x)
+
+
+def begin ():
+    """Start a data structure transaction.
+
+    Make a control point for being able to discard or undo
+    all operations done during this transaction.
+    """
+    ModelAPI.ModelAPI_Session.get().startOperation()
+
+
+def end ():
+    """Commit the data structure transaction.
+
+    Make all operations done since the last control point undo-able.
+    """
+    ModelAPI.ModelAPI_Session.get().finishOperation()
+
+
+def do ():
+    """Commit the data structure transaction and start the new one.
+
+    Make all operations done since the last control point undo-able
+    and continue with the new transaction.
+    """
+    session = ModelAPI.ModelAPI_Session.get()
+    session.finishOperation()
+    session.startOperation()
+
+
+def undo ():
+    """Roll-back the data structure to the previous control point."""
+    ModelAPI.ModelAPI_Session.get().undo()
+
+
+def redo ():
+    """Restore the data structure rolled-back by the last undo."""
+    ModelAPI.ModelAPI_Session.get().redo()
+
+
+def reset ():
+    """Reset the data structure to initial state."""
+    ModelAPI.ModelAPI_Session.get().closeAll()
diff --git a/src/PythonAPI/model/sketcher/__init__.py b/src/PythonAPI/model/sketcher/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/PythonAPI/model/sketcher/arc.py b/src/PythonAPI/model/sketcher/arc.py
new file mode 100644 (file)
index 0000000..0a7ae43
--- /dev/null
@@ -0,0 +1,94 @@
+"""Sketch circle feature interface."""
+
+from GeomDataAPI import geomDataAPI_Point2D
+from model.errors import WrongNumberOfArguments
+from model.roots import Interface
+
+class Arc(Interface):
+    """Interface to a sketch arc feature."""
+    def __init__(self, feature, *args):
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "SketchArc")
+
+        self._center = geomDataAPI_Point2D(
+            self._feature.data().attribute("ArcCenter")
+            )
+        self._start_point = geomDataAPI_Point2D(
+            self._feature.data().attribute("ArcStartPoint")
+            )
+        self._end_point = geomDataAPI_Point2D(
+            self._feature.data().attribute("ArcEndPoint")
+            )
+        if len(args) == 6:
+            self.__createByCoordinates(*args)
+        elif len(args) == 3:
+            self.__createByPoints(*args)
+        else:
+            raise WrongNumberOfArguments(
+                "Arc takes 3 or 6 arguments (%s given)" % len(args)
+                )
+        self.execute()
+        
+    ########
+    #
+    # Set methods
+    #
+    ########
+    
+    def setCenter(self, x, y):
+        """Set arc center."""
+        self._center.setValue(x, y)
+        
+    def setStartPoint(self, x, y):
+        """Set start point."""
+        self._start_point.setValue(x, y)
+        
+    def setEndPoint(self, x, y):
+        """Set end point value."""
+        self._end_point.setValue(x, y)
+        
+    
+    ########
+    #
+    # Getters
+    #
+    ########
+
+
+    def centerData(self):
+        """Return the center point data."""
+        return self._center
+
+    def startPointData(self):
+        """Return the start point data."""
+        return self._start_point
+
+    def endPointData(self):
+        """Return the end point data."""
+        return self._end_point
+
+    def result(self):
+        """Return the arc circular line attribute."""
+        return self._feature.lastResult()
+
+
+    ########
+    #
+    # Private methods
+    #
+    ########
+
+
+    def __createByCoordinates(self, center_x, center_y,
+                              start_x, start_y,
+                              end_x, end_y):
+        """Create an arc by point coordinates."""
+        self.setCenter(center_x, center_y)
+        self.setStartPoint(start_x, start_y)
+        self.setEndPoint(end_x, end_y)
+
+    def __createByPoints(self, center, start, end):
+        """Create an arc with point objects."""
+        self.setCenter(center.x(), center.y())
+        self.setStartPoint(start.x(), start.y())
+        self.setEndPoint(end.x(), end.y())
diff --git a/src/PythonAPI/model/sketcher/circle.py b/src/PythonAPI/model/sketcher/circle.py
new file mode 100644 (file)
index 0000000..b6ce45e
--- /dev/null
@@ -0,0 +1,38 @@
+"""Sketch circle feature interface."""
+
+from GeomDataAPI import geomDataAPI_Point2D
+from model.roots import Interface
+
+class Circle(Interface):
+    """Interface for circle feature data manipulation."""
+    def __init__(self, feature, x, y, radius):
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "SketchCircle")
+        
+        self._center = geomDataAPI_Point2D(
+            self._feature.data().attribute("CircleCenter")
+            )
+        self._radius = self._feature.data().real("CircleRadius")
+        self.setCenter(x, y)
+        self.setRadius(radius)
+        self.execute()
+
+    def setCenter(self, x, y):
+        """Set the center of the circle."""
+        self._center.setValue(x, y)
+        
+    def setRadius(self, radius):
+        """Set the radius of the circle."""
+        self._radius.setValue(radius)
+        
+    def centerData(self):
+        """Return center data."""
+        return self._center
+
+    def radiusData(self):
+        """Return radius data."""
+        return self._radius
+
+    def result(self):
+        """Return the cicular line attribute."""
+        return self._feature.lastResult()
diff --git a/src/PythonAPI/model/sketcher/line.py b/src/PythonAPI/model/sketcher/line.py
new file mode 100644 (file)
index 0000000..426ea97
--- /dev/null
@@ -0,0 +1,72 @@
+from GeomDataAPI import geomDataAPI_Point2D
+from model.roots import Interface
+from model.errors import WrongNumberOfArguments
+
+class Line(Interface):
+    """Interface for editing of a sketch line feature."""
+    def __init__(self, feature, *args):
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "SketchLine")
+
+        # Initialize attributes
+        self._start_point = geomDataAPI_Point2D(
+            self._feature.data().attribute("StartPoint")
+            )
+        self._end_point = geomDataAPI_Point2D(
+            self._feature.data().attribute("EndPoint")
+            )
+
+        # Check that input arguments are not None
+        if args is None:
+            raise WrongNumberOfArguments(
+                "No argument given, at least one argument needed"
+                )
+        
+        # Set attribute values and execute
+        if len(args) == 4:
+            self.__createByCoordinates(*args)
+        elif len(args) == 2:
+            self.__createByPoints(*args)
+        elif len(args) == 1:
+            self.__createByName(*args)
+        else:
+            raise WrongNumberOfArguments(
+                "Arc takes 1, 2 or 4 arguments (%s given)" % len(args)
+                )
+        self.execute()
+
+    def __createByCoordinates(self, x1, y1, x2, y2):
+        self.setStartPoint(x1, y1)
+        self.setEndPoint(x2, y2)
+
+    def __createByPoints(self, p1, p2):
+        self.setStartPoint(p1.x(), p1.y())
+        self.setEndPoint(p2.x(), p2.y())
+
+    def __createByName(self, name):
+        self._feature.data().selection("External").selectSubShape("EDGE", name)
+    
+    #######
+    #
+    # Set methods
+    #
+    #######
+    
+    def setStartPoint(self, x, y):
+        """Set the start point of the line."""
+        self._start_point.setValue(x, y)
+        
+    def setEndPoint(self, x, y):
+        """Set the end point of the line."""
+        self._end_point.setValue(x, y)
+
+    # TODO : methods below will be removed.
+    # Kept until all tests have been updated
+    def startPointData(self):
+        return self._start_point
+
+    def endPointData(self):
+        return self._end_point
+
+    def result(self):
+        return self._feature.firstResult()
diff --git a/src/PythonAPI/model/sketcher/point.py b/src/PythonAPI/model/sketcher/point.py
new file mode 100644 (file)
index 0000000..603a623
--- /dev/null
@@ -0,0 +1,30 @@
+"""Sketch point feature interface."""
+
+from GeomDataAPI import geomDataAPI_Point2D
+from model.roots import Interface
+from model.errors import FeatureInputInvalid
+
+class Point(Interface):
+    """Interface on point feature for data manipulation."""
+    def __init__(self, feature, x, y):
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "SketchPoint")
+        
+        # Initialize attributes of the feature
+        self._point_data = geomDataAPI_Point2D(
+            self._feature.data().attribute("PointCoordinates")
+            )
+        self.setValue(x, y)
+        self.execute()
+
+    def setValue(self, x, y):
+        """Set point coordinates."""
+        self._point_data.setValue(x, y)
+
+    def pointData (self):
+        """Return the point data."""
+        return self._point_data
+
+    def result (self):
+        """Return the feature result."""
+        return self._point_feature.firstResult()
diff --git a/src/PythonAPI/model/sketcher/sketch.py b/src/PythonAPI/model/sketcher/sketch.py
new file mode 100644 (file)
index 0000000..d0dfcf6
--- /dev/null
@@ -0,0 +1,336 @@
+"""Sketch Feature Interface
+Author: Daniel Brunier-Coulin with contribution by Mikhail Ponikarov
+        finalized by Renaud Nedelec and Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from ModelAPI import modelAPI_ResultConstruction, featureToCompositeFeature
+from GeomDataAPI import geomDataAPI_Point, geomDataAPI_Dir
+from GeomAlgoAPI import GeomAlgoAPI_SketchBuilder, ShapeList
+
+from model.sketcher.point import Point
+from model.sketcher.line import Line
+from model.sketcher.circle import Circle
+from model.sketcher.arc import Arc
+from model.roots import Interface
+from model.tools import Selection
+
+
+def addSketch(doc, plane):
+    """Add a Sketch feature to the Part or PartSet and return an interface
+    on it.
+
+    A Sketch object is instanciated with a feature as input parameter
+    it provides an interface for manipulation of the feature data.
+    :return: interface on the feature
+    :rtype: Sketch"""
+    feature = featureToCompositeFeature(doc.addFeature("Sketch"))
+    return Sketch(feature, plane)
+
+class Sketch(Interface):
+    """Interface class for Sketch feature."""
+    def __init__(self, feature, *args):
+        """Initialize a 2D Sketch on the given plane.
+
+        The plane can be defined either by:
+        - a 3D axis system (geom.Ax3),
+        - an existing face identified by its topological name.
+        """
+        Interface.__init__(self, feature)
+        assert(self._feature.getKind() == "Sketch")
+
+        self._origin = geomDataAPI_Point(
+            self._feature.data().attribute("Origin")
+            )
+        self._dir_x = geomDataAPI_Dir(
+            self._feature.data().attribute("DirX")
+            )
+        self._norm = geomDataAPI_Dir(
+            self._feature.data().attribute("Norm")
+            )
+        self._external = self._feature.data().selection("External")
+
+        assert(self._origin)
+        assert(self._dir_x)
+        assert(self._norm)
+        assert(self._external)
+
+        if not args:
+            return
+
+        plane = args[0]
+
+        #   self.resultype ="Face" # Type of Sketch result
+        if isinstance(plane, str):
+            self.__sketchOnFace(plane)
+        else:
+            self.__sketchOnPlane(plane)
+        pass
+
+    def __sketchOnPlane(self, plane):
+        """Create the sketch on a plane."""
+        origin = plane.location()
+        normal = plane.direction()
+        x_direction = plane.xDirection()
+        self._origin.setValue(origin.x(), origin.y(), origin.z())
+        self._norm.setValue(normal.x(), normal.y(), normal.z())
+        self._dir_x.setValue(x_direction.x(), x_direction.y(), x_direction.z())
+
+    def __sketchOnFace(self, name):
+        """Initialize the sketch on a face given by its name."""
+        self._external.selectSubShape("FACE", name)
+
+    #-------------------------------------------------------------
+    #
+    # Creation of Geometries
+    #
+    #-------------------------------------------------------------
+
+    def addPoint(self, *args):
+        """Add a point to this Sketch."""
+        point_feature = self._feature.addFeature("SketchPoint")
+        return Point(point_feature, *args)
+
+    def addLine(self, *args):
+        """Add a line to this Sketch."""
+        line_feature = self._feature.addFeature("SketchLine")
+        line_interface = Line(line_feature, *args)
+        # if the line is created by name add a rigid constraint
+        # to the created line
+        if len(args) == 1 and isinstance(args[0], str):
+            constraint = self._feature.addFeature("SketchConstraintRigid")
+            constraint.refattr("ConstraintEntityA").setObject(
+                line_feature.firstResult()
+                )
+        return line_interface
+
+    def addCircle(self, *args):
+        """Add a circle to this Sketch."""
+        circle_feature = self._feature.addFeature("SketchCircle")
+        return Circle(circle_feature, *args)
+
+    def addArc(self, *args):
+        """Add an arc to this Sketch."""
+        arc_feature = self._feature.addFeature("SketchArc")
+        return Arc(arc_feature, *args)
+
+    #-------------------------------------------------------------
+    #
+    # Creation of Geometrical and Dimensional Constraints
+    #
+    #-------------------------------------------------------------
+
+    def setCoincident(self, p1, p2):
+        """Set coincident the two given points and add the corresponding
+        constraint to this Sketch."""
+        assert(p1 and p2)
+        constraint = self._feature.addFeature("SketchConstraintCoincidence")
+        constraint.data().refattr("ConstraintEntityA").setAttr(p1)
+        constraint.data().refattr("ConstraintEntityB").setAttr(p2)
+        self.execute()
+        return constraint
+
+    def setParallel(self, l1, l2):
+        """Set parallel the two given lines and add the corresponding
+        constraint to this Sketch."""
+        assert(l1 and l2)
+        constraint = self._feature.addFeature("SketchConstraintParallel")
+        constraint.data().refattr("ConstraintEntityA").setObject(l1)
+        constraint.data().refattr("ConstraintEntityB").setObject(l2)
+        self.execute()
+        return constraint
+
+    def setPerpendicular(self, l1, l2):
+        """Set perpendicular the two given lines and add the corresponding
+        constraint to this Sketch."""
+        assert(l1 and l2)
+        constraint = self._feature.addFeature("SketchConstraintPerpendicular")
+        constraint.data().refattr("ConstraintEntityA").setObject(l1)
+        constraint.data().refattr("ConstraintEntityB").setObject(l2)
+        self.execute()
+        return constraint
+
+    def setHorizontal(self, line):
+        """Set horizontal the given line and add the corresponding
+        constraint to this Sketch."""
+        constraint = self._feature.addFeature("SketchConstraintHorizontal")
+        constraint.data().refattr("ConstraintEntityA").setObject(line)
+        self.execute()
+        return constraint
+
+    def setVertical(self, line):
+        """Set vertical the given line and add the corresponding
+        constraint to this Sketch."""
+        constraint = self._feature.addFeature("SketchConstraintVertical")
+        constraint.data().refattr("ConstraintEntityA").setObject(line)
+        self.execute()
+        return constraint
+
+    def setDistance(self, point, line, length):
+        """Set the distance between the given point and line, and add
+        the corresponding constraint to this Sketch."""
+        assert(point and line)
+        constraint = self._feature.addFeature("SketchConstraintDistance")
+        if isinstance(line, basestring):
+            # Add the edge identified by the given topological name
+            # to this Sketch
+            line = self.addLine(line).result()
+            assert(line)
+        constraint.data().refattr("ConstraintEntityA").setAttr(point)
+        constraint.data().refattr("ConstraintEntityB").setObject(line)
+        constraint.data().real("ConstraintValue").setValue(length)
+        self.execute()
+        return constraint
+
+    def setLength(self, line, length):
+        """Set the length of the given line and add the corresponding
+        constraint to this Sketch."""
+        assert(line)
+        constraint = self._feature.addFeature("SketchConstraintLength")
+        constraint.data().refattr("ConstraintEntityA").setObject(line)
+        constraint.data().real("ConstraintValue").setValue(length)
+        self.execute()
+        return constraint
+
+    def setRadius(self, circle, radius):
+        """Set the radius of the given circle and add the corresponding
+        constraint to this Sketch."""
+        constraint = self._feature.addFeature("SketchConstraintRadius")
+        constraint.data().refattr("ConstraintEntityA").setObject(circle)
+        constraint.data().real("ConstraintValue").setValue(radius)
+        self.execute()
+        return constraint
+
+    def setEqual(self, object_1, object_2):
+        """Set the radii of two circles or the length of two lines equal.
+
+        The corresponding constraint is added to the sketch"""
+        constraint = self._feature.addFeature("SketchConstraintEqual")
+        constraint.data().refattr("ConstraintEntityA").setObject(object_1)
+        constraint.data().refattr("ConstraintEntityB").setObject(object_2)
+        self.execute()
+        return constraint
+
+    def setAngle(self, line_1, line_2, angle):
+        """Set the angle between the given 2 lines and add the corresponding
+        constraint to the sketch."""
+        constraint = self._feature.addFeature("SketchConstraintAngle")
+        constraint.data().refattr("ConstraintEntityA").setObject(line_1)
+        constraint.data().refattr("ConstraintEntityB").setObject(line_2)
+        constraint.data().real("ConstraintValue").setValue(angle)
+        self.execute()
+        return constraint
+
+    def setTangent(self, object_1, object_2):
+        """Set a tangential continuity between two objects
+        at their coincidence point."""
+        constraint = self._feature.addFeature("SketchConstraintTangent")
+        constraint.data().refattr("ConstraintEntityA").setObject(object_1)
+        constraint.data().refattr("ConstraintEntityB").setObject(object_2)
+        self.execute()
+        return constraint
+
+    def setFillet(self, line_1, line_2, radius):
+        """Set a fillet constraint between the 3 given lines with the given
+        filleting radius."""
+        constraint = self._feature.addFeature("SketchConstraintFillet")
+        constraint.data().refattr("ConstraintEntityA").setObject(line_1)
+        constraint.data().refattr("ConstraintEntityB").setObject(line_2)
+        constraint.data().real("ConstraintValue").setValue(radius)
+        self.execute()
+        return constraint
+
+    #-------------------------------------------------------------
+    #
+    # Edition of Dimensional Constraints
+    #
+    #-------------------------------------------------------------
+
+    def setValue(self, constraint, value):
+        """Modify the value of the given dimensional constraint."""
+        constraint.data().real("ConstraintValue").setValue(value)
+
+    #-------------------------------------------------------------
+    #
+    # Macro functions combining geometry creation and constraints
+    #
+    #-------------------------------------------------------------
+
+    def addPolyline(self, *coords):
+        """Add a poly-line to this Sketch.
+
+        The end of consecutive segments are defined as coincident.
+        """
+        c0 = coords[0]
+        c1 = coords[1]
+        polyline = []
+        line_1 = self.addLine(c0, c1)
+        polyline.append(line_1)
+        # Adding and connecting next lines
+        for c2 in coords[2:]:
+            line_2 = self.addLine(c1, c2)
+            self.setCoincident(line_1.endPointData(), line_2.startPointData())
+            polyline.append(line_2)
+            c1 = c2
+            line_1 = line_2
+        return polyline
+
+    def addPolygon(self, *coords):
+        """Add a polygon to this Sketch.
+
+        The end of consecutive segments are defined as coincident.
+        """
+        pg = self.addPolyline(*coords)
+        # Closing the poly-line supposed being defined by at least 3 points
+        c0 = coords[0]
+        cn = coords[len(coords) - 1]
+        ln = self.addLine(cn, c0)
+        self.setCoincident(
+            pg[len(coords) - 2].endPointData(), ln.startPointData()
+            )
+        self.setCoincident(
+            ln.endPointData(), pg[0].startPointData()
+            )
+        pg.append(ln)
+        return pg
+
+    #-------------------------------------------------------------
+    #
+    # Getters
+    #
+    #-------------------------------------------------------------
+
+    def selectFace(self, *args):
+        """Select the geometrical entities of this Sketch on which
+        the result Face must be built.
+
+        When no entity is given, the face is based on all existing
+        geometry of this Sketch.
+        """
+        if len(args) == 0:
+            wire = modelAPI_ResultConstruction(
+                self._feature.firstResult()
+                ).shape()
+        elif len(args) == 1:
+            wire = args[0].shape()
+        else:
+            raise Exception("not yet implemented")
+        # TODO: simple version now, should be a list of selected faces
+        return [Selection(self.result(), self.buildShape(wire))]
+
+    def buildShape(self, wire):
+        """Build the result Shape of this Sketch according to the
+        selected geometrical entities."""
+        o = self._origin.pnt()
+        dx = self._dir_x.dir()
+        n = self._norm.dir()
+
+        # The faces are kept otherwise they are destroyed at exit
+        faces = ShapeList()
+        GeomAlgoAPI_SketchBuilder.createFaces(o, dx, n, wire, faces)
+        # TODO: Deal with several faces
+        return faces[0]
+
+    def result(self):
+        """Returns the result data of this Feature."""
+        return self._feature.firstResult()
diff --git a/src/PythonAPI/model/tools.py b/src/PythonAPI/model/tools.py
new file mode 100644 (file)
index 0000000..9971e4b
--- /dev/null
@@ -0,0 +1,126 @@
+"""Common tools for other modules.
+Author: Sergey Pokhodenko
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+import re
+import collections
+
+import ModelAPI
+import GeomAPI
+import GeomDataAPI
+
+# from .sketcher.sketch import Sketch
+
+
+def convert_to_underscore(name):
+    """Convert CamelCase to underscore_case."""
+    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
+    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
+
+
+class Selection:
+    """Class for selection.
+
+    Selection() -> empty selection
+    Selection(name, type) -> selection initialized with arguments:
+        - name -- topological name
+        - type -- type of the object
+    Selection(context, shape) -> selection initialized with arguments:
+        - context -- ModelAPI_Result object
+        - shape -- GeomAPI_Shape shape
+    """
+
+    def __init__(self, *args):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+
+        if not args:
+            self.args = (None, None)
+            return
+
+        if len(args) == 1 and isinstance(args[0], basestring):
+            self.args = args
+            return
+
+        assert(len(args) > 1 and len(args) < 4)
+        assert(isinstance(args[0], basestring) or
+               isinstance(args[0], ModelAPI.ModelAPI_Result))
+        if isinstance(args[0], basestring):
+            assert(isinstance(args[1], basestring))
+        elif isinstance(args[0], ModelAPI.ModelAPI_Result) or args[0] is None:
+            assert(isinstance(args[1], GeomAPI.GeomAPI_Shape))
+        self.args = args
+
+
+def fill_attribute(attribute, value):
+    """Set value to attribure.
+
+    This function processes complex cases.
+    ModelAPI_AttributeSelectionList can accept string, result + shape, list of
+    strings and [result + shape]...
+    ModelAPI_AttributeDouble can accept float and string
+    """
+    if (isinstance(attribute, ModelAPI.ModelAPI_AttributeBoolean) or
+        isinstance(attribute, ModelAPI.ModelAPI_AttributeDocRef) or
+        isinstance(attribute, ModelAPI.ModelAPI_AttributeInteger) or
+        isinstance(attribute, ModelAPI.ModelAPI_AttributeReference) or
+        isinstance(attribute, ModelAPI.ModelAPI_AttributeString)
+        ):
+        attribute.setValue(value)
+
+    elif isinstance(attribute, ModelAPI.ModelAPI_AttributeDouble):
+        if isinstance(value, basestring):
+            attribute.setText(value)
+        else:
+            attribute.setValue(value)
+
+    elif isinstance(attribute, ModelAPI.ModelAPI_AttributeIntArray):
+        attrubute.setSize(len(value))
+        for i in range(len(value)):
+            attrubute.setValue(i, value[i])
+
+    elif isinstance(attribute, ModelAPI.ModelAPI_AttributeRefAttr):
+        assert(isinstance(value, ModelAPI.ModelAPI_Attribute) or
+               isinstance(value, ModelAPI.ModelAPI_Object))
+        if isinstance(value, ModelAPI.ModelAPI_Attribute):
+            attrubute.setAttr(value)
+        elif isinstance(value, ModelAPI.ModelAPI_Object):
+            attrubute.setObject(value)
+
+    elif isinstance(attribute, ModelAPI.ModelAPI_AttributeRefList):
+        attribute.clear()
+        if not value:
+            return
+
+        assert(isinstance(value, collections.Iterable))
+        for item in value:
+            assert(isinstance(item, ModelAPI.ModelAPI_Object))
+            attribute.append(item)
+
+    elif isinstance(attribute, ModelAPI.ModelAPI_AttributeSelection):
+        if value is None:
+            attribute.setValue(None, None)
+            return
+
+        assert(isinstance(value, Selection))
+        attribute.setValue(*value.args)
+
+    elif isinstance(attribute, ModelAPI.ModelAPI_AttributeSelectionList):
+        attribute.clear()
+        if not value:
+            return
+
+        assert(isinstance(value, collections.Iterable))
+        for item in value:
+            assert(isinstance(item, Selection))
+            attribute.append(*item.args)
+
+    elif (isinstance(attribute, GeomDataAPI.GeomDataAPI_Dir) or
+          isinstance(attribute, GeomDataAPI.GeomDataAPI_Point) or
+          isinstance(attribute, GeomDataAPI.GeomDataAPI_Point2D)
+          ):
+        assert(isinstance(value, collections.Iterable))
+        attribute.setValue(*value)
+
+    else:
+        raise AssertionError("Wrong attribute type: %s" % type(attribute))
diff --git a/src/PythonAPI/modeler/__init__.py b/src/PythonAPI/modeler/__init__.py
deleted file mode 100644 (file)
index 8ffaa38..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-"""This package defines the Parametric Geometry API of the Modeler.
-"""
-
-# General purpose functions and abstract root classes
-
-from services  import *
-from roots     import *
-
-# Built-in features
-
-from part      import Part         as addPart
-from sketcher  import Sketch       as addSketch
-from extrusion import Extrusion    as addExtrusion
-from boolean   import Addition     as addAddition
-from boolean   import Subtraction  as addSubtraction
-from boolean   import Intersection as addIntersection
\ No newline at end of file
diff --git a/src/PythonAPI/modeler/services.py b/src/PythonAPI/modeler/services.py
deleted file mode 100644 (file)
index d463c59..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-"""General purpose Interface
-Author: Daniel Brunier-Coulin
-Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-"""
-
-from ModelAPI import *
-from GeomAPI  import *
-import geom              # To be removed when gp_Ax3 will be Pythonized
-
-
-def moduleDocument ():
-  """Returns the main document (the Partset) created or open from the Modeler.
-  This document is unique in the application session.
-  """
-  return ModelAPI_Session.get().moduleDocument()
-
-
-def activeDocument ():
-  """Returns the active document.
-  This document can be either the main application document (i.e. the Partset) or one of documents
-  referred to by the main document (a Part).
-  """
-  return ModelAPI_Session.get().activeDocument()
-
-
-def defaultPlane (name):
-  """Returns one of the three planes defined by the global coordinate system.
-  These planes are respectively referred to by name "XOY" (Z=0), "XOZ" (Y=0) or "YOZ" (X=0).
-  """
-# Temporary implementation before the availability of default planes.
-
-  o = GeomAPI_Pnt( 0, 0, 0 )
-  if   name == "XOY":
-    n = GeomAPI_Dir( 0, 0, 1)
-    x = GeomAPI_Dir( 1, 0, 0)
-  elif name == "XOZ":
-    n = GeomAPI_Dir( 0, 1, 0)
-    x = GeomAPI_Dir( 1, 0, 0)
-  elif name == "YOZ":
-    n = GeomAPI_Dir( 1, 0, 0)
-    x = GeomAPI_Dir( 0, 1, 0)
-
-  return geom.Ax3( o, n, x )
-
-
-def begin ():
-  """Starts a data structure transaction, as such making a control point for being able to discard or undo
-  all operations done during this transaction.
-  """
-  ModelAPI_Session.get().startOperation()
-
-
-def end ():
-  """Commits the data structure transaction and makes all operations done since the last control point undo-able."""
-  ModelAPI_Session.get().finishOperation()
-
-
-def do ():
-  """Commits the data structure transaction and makes all operations done since the last control point undo-able."""
-  session = ModelAPI_Session.get()
-  session.finishOperation()
-  session.startOperation()
-
-
-def undo ():
-  """Rolls-back the data structure to the previous control point."""
-  ModelAPI_Session.get().undo()
-
-
-def redo ():
-  """Restore the data structure rolled-back by the last undo."""
-  ModelAPI_Session.get().redo()
diff --git a/src/PythonAPI/pylintrc b/src/PythonAPI/pylintrc
new file mode 100644 (file)
index 0000000..d1ef322
--- /dev/null
@@ -0,0 +1,283 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time. See also the "--disable" option for examples.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+#disable=
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html. You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details
+#msg-template=
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+#function-rgx=[a-z_][a-z0-9_]{2,30}$
+function-rgx=[a-z][a-zA-Z0-9]*$
+
+# Regular expression which should only match correct method names
+#method-rgx=[a-z_][a-z0-9_]{2,30}$
+# __get_state__ etc. are not camel case, so we add an 'OR' to the regex
+method-rgx=[a-z][a-zA-Z0-9]*|__[a-z_]*__$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct attribute names in class
+# bodies
+class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=__.*__
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=80
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+# List of optional constructs for which whitespace checking is disabled
+no-space-check=trailing-comma,dict-separator
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string='    '
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_$|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff --git a/src/PythonAPI/shaper.py b/src/PythonAPI/shaper.py
new file mode 100644 (file)
index 0000000..b2eb4d4
--- /dev/null
@@ -0,0 +1,7 @@
+"""This package defines the Python API of the Shaper.
+"""
+
+# Main packages
+
+import geom
+import model
index 0c92f1be1b77f1f6bb466e7a0625e92adf1b791e..3fef980a8e2638086adb4f5c53d4310b8a042bd6 100644 (file)
@@ -6,17 +6,20 @@ from macros.box.feature      import BoxFeature
 
 
 class PythonFeaturesPlugin(ModelAPI.ModelAPI_Plugin):
-"""Implementation of features plugin"""
+    """Implementation of features plugin.
+
+    PythonFeaturesPlugin() -> plugin object
+    """
 
     def __init__(self):
-        """Constructor"""
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
         ModelAPI.ModelAPI_Plugin.__init__(self)
         aSession = ModelAPI.ModelAPI_Session.get()
         aSession.registerPlugin(self)
         pass
 
     def createFeature(self, theFeatureID):
-        """Create a feature by its Id"""
+        """Override ModelAPI_Plugin.createFeature()"""
         aFeature = None
 
         if theFeatureID == BoxFeature.ID():
@@ -27,6 +30,6 @@ class PythonFeaturesPlugin(ModelAPI.ModelAPI_Plugin):
 
         return aFeature
 
-### The plugin object
+# The plugin object
 plugin = PythonFeaturesPlugin()
 plugin.__disown__()
index 1f581be4aafb04b7d0ae67871f1469c18c08749c..ca037ba1f14d813a64c592e984bfce370ec610e4 100644 (file)
@@ -3,100 +3,107 @@ Authors: Renaud Nedelec - Daniel Brunier-Coulin
 Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 """
 
-import modeler
+import model
 import geom
 
 
-class BoxFeature(modeler.Feature):
-  """An example of Box feature implementation"""
+class BoxFeature(model.Feature):
+    """An example of Box feature implementation.
+
+    BoxFeature() -> Box
+    """
 
 # Initializations
 
-  def __init__(self):
-    """Constructor"""
-    modeler.Feature.__init__(self)
+    def __init__(self):
+        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+        model.Feature.__init__(self)
+
+    @staticmethod
+    def ID():
+        """Return Id of the feature."""
+        return "Box"
 
-  @staticmethod
-  def ID():
-    """Return Id of the feature"""
-    return "Box"
+    @staticmethod
+    def WIDTH_ID():
+        """Returns ID of Width parameter."""
+        return "width"
 
-  @staticmethod
-  def WIDTH_ID():
-    """Returns ID of Width parameter"""
-    return "width"
+    @staticmethod
+    def LENGTH_ID():
+        """Returns ID of Length parameter."""
+        return "length"
 
-  @staticmethod
-  def LENGTH_ID():
-    """Returns ID of Length parameter"""
-    return "length"
+    @staticmethod
+    def HEIGHT_ID():
+        """Returns ID of Height parameter."""
+        return "height"
 
-  @staticmethod
-  def HEIGHT_ID():
-    """Returns ID of Height parameter"""
-    return "height"
+    def getKind(self):
+        """Override Feature.getKind()"""
+        return BoxFeature.ID()
 
-  def getKind(self):
-    """Returns ID of еру ауфегку"""
-    return BoxFeature.ID()
 
-       
 # Creation of the box at default size
 
-  def initAttributes(self):
-    """Initialise attributes of the feature"""
-    # Creating the input arguments of the feature
-    self.addRealInput( self.WIDTH_ID() )
-    self.addRealInput( self.LENGTH_ID() )
-    self.addRealInput( self.HEIGHT_ID() )
+    def initAttributes(self):
+        """Override Feature.initAttributes()"""
+        # Creating the input arguments of the feature
+        self.addRealInput(self.WIDTH_ID())
+        self.addRealInput(self.LENGTH_ID())
+        self.addRealInput(self.HEIGHT_ID())
 
-    # Creating the base of the box with unit values
-    mypart = modeler.activeDocument()
-    xoy    = modeler.defaultPlane("XOY")
+        # Creating the base of the box with unit values
+        mypart = model.activeDocument()
+        xoy = model.defaultPlane("XOY")
 
-    ### A base of the geometry
-    self.base = modeler.addSketch( mypart, xoy )
+        # A base of the geometry
+        self.base = model.addSketch(mypart, xoy)
 
-    p1 = geom.Pnt2d( 0, 0 )
-    p2 = geom.Pnt2d( 0, 1 )
-    p3 = geom.Pnt2d( 1, 1 )
-    p4 = geom.Pnt2d( 1, 0 )
+        p1 = geom.Pnt2d(0, 0)
+        p2 = geom.Pnt2d(0, 1)
+        p3 = geom.Pnt2d(1, 1)
+        p4 = geom.Pnt2d(1, 0)
 
-    line = self.base.addPolygon(p1, p2, p3, p4)
+        line = self.base.addPolygon(p1, p2, p3, p4)
 
-    self.base.setParallel( line[0].result(), line[2].result() )
-    self.base.setParallel( line[1].result(), line[3].result() )
-    self.base.setPerpendicular( line[0].result(), line[3].result() )
+        self.base.setParallel(line[0].result(), line[2].result())
+        self.base.setParallel(line[1].result(), line[3].result())
+        self.base.setPerpendicular(line[0].result(), line[3].result())
 
-    # Setting the size of the base with default values
-    ### Width
-    self.width  = self.base.setLength( line[0].result(), 50 )   # Keeps the constraint for edition
-    ### Length
-    self.length = self.base.setLength( line[3].result(), 50 )   # Keeps the constraint for edition
+        # Setting the size of the base with default values
+        # Width
+        self.width = self.base.setLength(line[0].result(), 50)  # Keeps the constraint for edition
+        # Length
+        self.length = self.base.setLength(line[3].result(), 50)  # Keeps the constraint for edition
 
-    # Creating the extrusion (the box) at default size
-    ### A box result
-    self.box = modeler.addExtrusion( mypart, self.base.selectFace(), 50 )
+        # Creating the extrusion (the box) at default size
+        # A box result
+        self.box = model.addExtrusion(mypart, self.base.selectFace(), 50)
 
-       
 # Edition of the box at user size
 
-  def execute(self):
-    """Compute the feature result"""
-    # Retrieving the user inputs
-    width  = self.getRealInput( self.WIDTH_ID() )
-    length = self.getRealInput( self.LENGTH_ID() )
-    height = self.getRealInput( self.HEIGHT_ID() )
-
-    # Editing the box
-    self.base.setValue( self.width,  width )
-    self.base.setValue( self.length, length )
-    self.box.setSize( height )
-
-    # Publishing the result: not needed for Macro feature
-    #self.addResult( self.box.result() )
-  
-  def isMacro(self):
-    """Returns True"""
-    # Box feature is macro: removes itself on the creation transaction finish
-    return True
+    def execute(self):
+        """F.execute() -- execute the feature"""
+        # Retrieving the user inputs
+        width = self.getRealInput(self.WIDTH_ID())
+        length = self.getRealInpuut(self.WIDTH_ID())
+        length = self.getRealInt(self.LENGTH_ID())
+        height = self.getRealInput(self.HEIGHT_ID())
+
+        # Editing the box
+        self.base.setValue(self.width, width)
+        self.base.setValue(self.length, length)
+        self.box.setSize(height)
+
+        # Publishing the result: not needed for Macro feature
+        # self.addResult( self.box.result() )
+
+    def isMacro(self):
+        """Override Feature.initAttributes().
+        F.isMacro() -> True
+
+        Box feature is macro: removes itself on the creation transaction
+        finish.
+        """
+        return True
index 59995ff4310aeb44edc72c2f950f4d3e09c0c119..1e1a4f65cc842ac70804ab32dbfa3bc6368fdb60 100644 (file)
@@ -28,7 +28,7 @@ class SketchPlugin_Point : public SketchPlugin_SketchEntity
   /// Coordinates of the point
   inline static const std::string& COORD_ID()
   {
-    static const std::string MY_COORD_ID("PointCoordindates");
+    static const std::string MY_COORD_ID("PointCoordinates");
     return MY_COORD_ID;
   }
   /// Returns the kind of a feature
index 3891315ef09cb141d9000fe39864c018da3bee43..26e7c2989f7ef66debc89fdac31b28635c02f5f2 100644 (file)
@@ -18,7 +18,7 @@
       <!--icon=":pictures/x_point.png"-->
       </feature>
       <feature id="SketchPoint" title="Point" tooltip="Create point" icon=":icons/point.png">
-        <sketch-2dpoint_selector id="PointCoordindates" title="Point" tooltip="Point coordinates"/>
+        <sketch-2dpoint_selector id="PointCoordinates" title="Point" tooltip="Point coordinates"/>
         <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
       </feature>
       <feature id="SketchLine" title="Line" tooltip="Create line" icon=":icons/line.png">