]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Correction for the RC1 version from the current master version. SHAPER_V9_1_0RC2
authormpv <mpv@opencascade.com>
Wed, 5 Sep 2018 07:41:22 +0000 (10:41 +0300)
committermpv <mpv@opencascade.com>
Wed, 5 Sep 2018 07:41:22 +0000 (10:41 +0300)
28 files changed:
env.sh
env_linux.sh
env_salome.sh
src/ExchangeAPI/ExchangeAPI_Export.cpp
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/boolean_fill_widget.xml [new file with mode: 0644]
src/FeaturesPlugin/plugin-Features.xml
src/GeomAPI/CMakeLists.txt
src/GeomAPI/GeomAPI.i
src/GeomAPI/GeomAPI_Cone.cpp
src/GeomAPI/GeomAPI_Face.cpp
src/GeomAPI/GeomAPI_Pnt.cpp
src/GeomAPI/GeomAPI_Pnt.h
src/GeomAPI/GeomAPI_Shell.cpp
src/GeomAPI/GeomAPI_Solid.cpp
src/GeomAPI/GeomAPI_Wire.cpp
src/GeomAPI/GeomAPI_swig.h
src/GeomAPI/Test/TestBox.py [new file with mode: 0644]
src/GeomAPI/Test/TestCone.py [new file with mode: 0644]
src/GeomAPI/Test/TestCylinder.py [new file with mode: 0644]
src/GeomAPI/Test/TestPolygon.py [new file with mode: 0644]
src/GeomAPI/Test/TestSphere.py [new file with mode: 0644]
src/GeomAPI/Test/TestTorus.py [new file with mode: 0644]
src/GeomValidators/GeomValidators_NotSelfIntersected.cpp
src/InitializationPlugin/CMakeLists.txt
src/ModelAPI/ModelAPI.i
src/ModuleBase/ModuleBase_WidgetIntValue.cpp
src/SketchPlugin/plugin-Sketch.xml

diff --git a/env.sh b/env.sh
index 7091b84af286c4275bef6ce7b116b480f388c5e3..2edade92ef00645a635170049d39de9208a0fe72 100644 (file)
--- a/env.sh
+++ b/env.sh
@@ -11,11 +11,12 @@ export AUT_DIR=$(pwd)
 export TOOLS_DIR=$(pwd)
 
 export HOME_OLD=$HOME
-source /dn46/SALOME/series9x/current-2018-08-22/start.sh
+source /dn46/SALOME/series9x/current-2018-08-30/start.sh
 export HOME=$HOME_OLD
 
-# Path to solvespace-2
+# Path to special products dir (lcov, cpplint)
 export SHAPER_PDIR=/dn48/newgeom/common/products
+
 # Path to install directory
 export SHAPER_ROOT_DIR=$(cd ${SOURCES_DIR}/.. && pwd)/install
 
index 5beff47b467a1e0e9ed4e2ac1a26a76f05fcac9d..d6cf38269b8046626dac346450c1e0ec19024966 100644 (file)
@@ -2,7 +2,7 @@
 
 # This script uses:
 #
-# SHAPER_PDIR - path of PRODUCTS for SHAPER (SolveSpace, lcov, cpplint)
+# SHAPER_PDIR - path of PRODUCTS for SHAPER (lcov, cpplint)
 # SHAPER_ROOT_DIR - path of SHAPER installation
 
 for path in SHAPER_PDIR SHAPER_ROOT_DIR; do
@@ -13,24 +13,6 @@ for path in SHAPER_PDIR SHAPER_ROOT_DIR; do
   fi
 done
 
-#------ SolveSpace ------
-export SOLVESPACE_ROOT_DIR=${SHAPER_PDIR}/solvespace-2.1
-export LD_LIBRARY_PATH=${SOLVESPACE_ROOT_DIR}/lib:${LD_LIBRARY_PATH}
-##
-
-#------ PlaneGCS ------
-export PLANEGCS_ROOT_DIR=${SHAPER_PDIR}/planegcs-0.16
-export LD_LIBRARY_PATH=${PLANEGCS_ROOT_DIR}/lib:${LD_LIBRARY_PATH}
-##
-
-#------ Eigen ------
-export EIGEN_ROOT_DIR=${SHAPER_PDIR}/eigen-3.2.7
-##
-
-#------ Boost ------
-export BOOST_ROOT_DIR=${SHAPER_PDIR}/boost-1.52.0
-##
-
 #------ lcov ------
 export LCOV_ROOT_DIR=${SHAPER_PDIR}/lcov-1.11
 export PATH=${LCOV_ROOT_DIR}/bin:${PATH}
@@ -41,16 +23,7 @@ export CPPLINT_ROOT_DIR=${SHAPER_PDIR}/cpplint-1.3.0
 export PATH=${CPPLINT_ROOT_DIR}:${PATH}
 ##
 
-#------ OCCT ------
-# Defaults
-export CSF_PluginDefaults=${CAS_ROOT_DIR}/share/opencascade/resources/StdResource
-export CSF_StandardDefaults=${CAS_ROOT_DIR}/share/opencascade/resources/StdResource
-# For CMake
-export LIB=${LD_LIBRARY_PATH}
-export PATH=${CASROOT}:${PATH}
-##
-
 #------ SHAPER ------
 export PATH=${SHAPER_ROOT_DIR}/bin/salome:${PATH}
-export PYTHONPATH=${SHAPER_ROOT_DIR}/bin/salome:${SHAPER_ROOT_DIR}/lib/python2.7/site-packages/salome:${PYTHONPATH}
+export PYTHONPATH=${SHAPER_ROOT_DIR}/bin/salome:${SHAPER_ROOT_DIR}/lib/python3.6/site-packages/salome:${PYTHONPATH}
 export LD_LIBRARY_PATH=${SHAPER_ROOT_DIR}/lib/salome:${LD_LIBRARY_PATH}
index ccaf3aebc577af9acc86c18e6e56c9568c3e99b4..60752255b29bfeb9d05746f58b85636c7c45a1fa 100644 (file)
@@ -1,5 +1,4 @@
 #!/bin/bash
 
-# Correcting path which defined with error
-export LD_LIBRARY_PATH=${KERNEL_ROOT_DIR}/lib/salome:${LD_LIBRARY_PATH}
+# Config path correction
 export SalomeAppConfig=${SHAPER_ROOT_DIR}/share/salome/resources/shaper:${GUI_ROOT_DIR}/share/salome/resources/gui
index 492479e5065ea40d9e929dfb58f4df4104880d7e..6165c8fa62e8cfa958cb6ba5f2090320e72a0276 100644 (file)
@@ -72,10 +72,28 @@ ExchangeAPI_Export::~ExchangeAPI_Export()
 {
 }
 
+// this method is needed on Windows because back-slashes in python may cause error
+static void correctSeparators(std::string& thePath) {
+  // replace single "\" or triple "\\\" or more by double "\"
+  for (std::size_t aFind = thePath.find('\\'); aFind != std::string::npos;
+    aFind = thePath.find('\\', aFind)) {
+    // search the next
+    std::size_t aFind2 = thePath.find('\\', aFind + 1);
+    if (aFind2 == std::string::npos || aFind2 > aFind + 1) { // single, so add one more
+      thePath.replace(aFind, 1, 2, '\\');
+    } else { // if there is more than double "\", remove them
+      for (aFind2 = thePath.find('\\', aFind2 + 1);
+           aFind2 != std::string::npos && aFind2 <= aFind + 2;
+           aFind2 = thePath.find('\\', aFind2)) {
+        thePath.erase(aFind2, 1);
+      }
+    }
+    aFind += 2;
+  }
+}
 
 void ExchangeAPI_Export::dump(ModelHighAPI_Dumper& theDumper) const
 {
-
   FeaturePtr aBase = feature();
   const std::string& aDocName = theDumper.name(aBase->document());
 
@@ -84,9 +102,10 @@ void ExchangeAPI_Export::dump(ModelHighAPI_Dumper& theDumper) const
   std::string exportType = aBase->string(ExchangePlugin_ExportFeature::EXPORT_TYPE_ID())->value();
 
   if (exportType == "XAO") {
-    std::string tmpXAOFile =
+    std::string aTmpXAOFile =
                 aBase->string(ExchangePlugin_ExportFeature::XAO_FILE_PATH_ID())->value();
-    theDumper << "exportToXAO(" << aDocName << ", '" << tmpXAOFile << "'" ;
+    correctSeparators(aTmpXAOFile);
+    theDumper << "exportToXAO(" << aDocName << ", '" << aTmpXAOFile << "'" ;
     std::string theAuthor = aBase->string(ExchangePlugin_ExportFeature::XAO_AUTHOR_ID())->value();
     if (! theAuthor.empty())
       theDumper << ", '" << theAuthor << "'";
@@ -97,14 +116,15 @@ void ExchangeAPI_Export::dump(ModelHighAPI_Dumper& theDumper) const
     theDumper << ")" << std::endl;
   }
   else {
-      theDumper << "exportToFile(" << aDocName << ", " <<
-          aBase->string(ExchangePlugin_ExportFeature::FILE_PATH_ID()) << ", " <<
-          aBase->selectionList(ExchangePlugin_ExportFeature::SELECTION_LIST_ID()) ;
-      std::string theFileFormat =
-                  aBase->string(ExchangePlugin_ExportFeature::FILE_FORMAT_ID())->value();
-      if (! theFileFormat.empty())
-        theDumper << ", '" << theFileFormat << "'";
-      theDumper << ")" << std::endl;
+    std::string aFilePath = aBase->string(ExchangePlugin_ExportFeature::FILE_PATH_ID())->value();
+    correctSeparators(aFilePath);
+      theDumper << "exportToFile(" << aDocName << ", \"" << aFilePath << "\", " <<
+      aBase->selectionList(ExchangePlugin_ExportFeature::SELECTION_LIST_ID());
+    std::string theFileFormat =
+      aBase->string(ExchangePlugin_ExportFeature::FILE_FORMAT_ID())->value();
+    if (!theFileFormat.empty())
+      theDumper << ", '" << theFileFormat << "'";
+    theDumper << ")" << std::endl;
   }
 }
 
index 11a8377a2561039dc887955bfe079f0e98360715..1bb74ed46a5657da153e31a244bb341e4421719b 100644 (file)
@@ -110,6 +110,7 @@ SET(XML_RESOURCES
   boolean_widget.xml
   boolean_fuse_widget.xml
   boolean_common_widget.xml
+  boolean_fill_widget.xml
   boolean_smash_widget.xml
   recover_widget.xml
   partition_widget.xml
diff --git a/src/FeaturesPlugin/boolean_fill_widget.xml b/src/FeaturesPlugin/boolean_fill_widget.xml
new file mode 100644 (file)
index 0000000..e584a53
--- /dev/null
@@ -0,0 +1,44 @@
+<!--
+Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See http:##www.salome-platform.org/ or
+email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+  <multi_selector id="main_objects"
+    label="Main objects"
+    icon=""
+    tooltip="Select objects"
+    type_choice="vertices edges wires faces shells solids compsolids compounds"
+    use_choice="false"
+    concealment="true">
+    <validator id="PartSet_DifferentObjects"/>
+    <validator id="FeaturesPlugin_ValidatorBooleanSelection"/>
+  </multi_selector>
+  <multi_selector id="tool_objects"
+    label="Tool objects"
+    icon=""
+    tooltip="Select tools"
+    type_choice="vertices edges wires faces shells solids compsolids compounds"
+    use_choice="false"
+    concealment="true" >
+    <validator id="PartSet_DifferentObjects"/>
+    <validator id="FeaturesPlugin_ValidatorBooleanSelection"/>
+  </multi_selector>
+  <validator id="FeaturesPlugin_ValidatorBooleanArguments" parameters="main_objects,tool_objects"/>
+</source>
index bb13f70af3184c6c6cd50cc10e6832e59e40cc3c..3858a8811735c30353c2bfce9506f69d9852ddf3 100644 (file)
@@ -94,7 +94,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
       <feature id="Fill" title="Fill" tooltip="Perform boolean fill operation with objects"
                icon="icons/Features/bool_fill.png" helpfile="FeaturesPlugin/fillFeature.html"
                auto_preview="false">
-          <source path="boolean_widget.xml"/>
+          <source path="boolean_fill_widget.xml"/>
       </feature>
       <feature id="Union" title="Union" tooltip="Perform union operations with shapes"
                icon="icons/Features/union.png" helpfile="FeaturesPlugin/unionFeature.html">
index 82b062a0c41cb57ae0f8f092911f6a4e73f6359d..4959dde28860961bc060f21b1b58f7acfcf5fe7e 100644 (file)
@@ -22,6 +22,7 @@ FIND_PACKAGE(SWIG REQUIRED)
 
 INCLUDE(${SWIG_USE_FILE})
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE(UnitTest)
 
 SET(PROJECT_HEADERS
     GeomAPI.h
@@ -157,3 +158,12 @@ ENDIF(WIN32)
 INSTALL(TARGETS _GeomAPI DESTINATION ${SHAPER_INSTALL_SWIG})
 INSTALL(TARGETS GeomAPI DESTINATION ${SHAPER_INSTALL_BIN})
 INSTALL(FILES ${SWIG_SCRIPTS} DESTINATION ${SHAPER_INSTALL_SWIG})
+
+ADD_UNIT_TESTS(
+  TestBox.py
+  TestCone.py
+  TestCylinder.py
+  TestPolygon.py
+  TestSphere.py
+  TestTorus.py
+)
index 82e29210883fd3a0b4e3e77cbdbf8a1372db6526..aa26482458d7cac892cda2ac8a9a319fe1a1ba03 100644 (file)
 
 // standard definitions
 %include "typemaps.i"
+%include "std_list.i"
 %include "std_string.i"
 %include "std_shared_ptr.i"
 
 // shared pointers
 %shared_ptr(GeomAPI_AISObject)
+%shared_ptr(GeomAPI_Angle)
+%shared_ptr(GeomAPI_Angle2d)
 %shared_ptr(GeomAPI_Ax1)
 %shared_ptr(GeomAPI_Ax2)
 %shared_ptr(GeomAPI_Ax3)
+%shared_ptr(GeomAPI_Box)
 %shared_ptr(GeomAPI_Circ)
 %shared_ptr(GeomAPI_Circ2d)
+%shared_ptr(GeomAPI_Cone)
 %shared_ptr(GeomAPI_Curve)
+%shared_ptr(GeomAPI_Cylinder)
 %shared_ptr(GeomAPI_DataMapOfShapeMapOfShapes)
 %shared_ptr(GeomAPI_DataMapOfShapeShape)
 %shared_ptr(GeomAPI_Dir)
 %shared_ptr(GeomAPI_Dir2d)
 %shared_ptr(GeomAPI_Edge)
+%shared_ptr(GeomAPI_Ellipse)
+%shared_ptr(GeomAPI_Ellipse2d)
 %shared_ptr(GeomAPI_Face)
 %shared_ptr(GeomAPI_ICustomPrs)
 %shared_ptr(GeomAPI_Interface)
 %shared_ptr(GeomAPI_Shape)
 %shared_ptr(GeomAPI_ShapeExplorer)
 %shared_ptr(GeomAPI_ShapeIterator)
+%shared_ptr(GeomAPI_Shell)
+%shared_ptr(GeomAPI_Solid)
+%shared_ptr(GeomAPI_Sphere)
+%shared_ptr(GeomAPI_Torus)
+%shared_ptr(GeomAPI_Trsf)
 %shared_ptr(GeomAPI_Vertex)
+%shared_ptr(GeomAPI_Wire)
 %shared_ptr(GeomAPI_XY)
 %shared_ptr(GeomAPI_XYZ)
-%shared_ptr(GeomAPI_Trsf)
-%shared_ptr(GeomAPI_Wire)
-%shared_ptr(GeomAPI_Shell)
-%shared_ptr(GeomAPI_Solid)
-%shared_ptr(GeomAPI_Box)
+
+
+%typemap(in) std::list<std::shared_ptr<GeomAPI_Pnt> > &thePoints (std::list<std::shared_ptr<GeomAPI_Pnt> > temp) {
+  std::shared_ptr<GeomAPI_Pnt> * temp_pnt;
+  int newmem = 0;
+  if (PySequence_Check($input)) {
+    for (Py_ssize_t i = 0; i < PySequence_Size($input); ++i) {
+      PyObject * item = PySequence_GetItem($input, i);
+      if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_pnt, $descriptor(std::shared_ptr<GeomAPI_Pnt> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+        if (!temp_pnt) {
+          PyErr_SetString(PyExc_TypeError, "argument must be list of GeomAPI_Pnt.");
+          return NULL;
+       }
+        temp.push_back(*temp_pnt);
+        if (newmem & SWIG_CAST_NEW_MEMORY) {
+          delete temp_pnt;
+        }
+      }
+      Py_DECREF(item);
+    }
+    $1 = &temp;
+  } else {
+    PyErr_SetString(PyExc_ValueError, "argument must be list of GeomAPI_Pnt.");
+    return NULL;
+  }
+}
 
 
 // all supported interfaces
 %include "GeomAPI_Interface.h"
 %include "GeomAPI_Shape.h"
 %include "GeomAPI_AISObject.h"
+%include "GeomAPI_Angle.h"
+%include "GeomAPI_Angle2d.h"
 %include "GeomAPI_Ax1.h"
 %include "GeomAPI_Ax2.h"
 %include "GeomAPI_Ax3.h"
+%include "GeomAPI_Box.h"
 %include "GeomAPI_Circ.h"
 %include "GeomAPI_Circ2d.h"
+%include "GeomAPI_Cone.h"
 %include "GeomAPI_Curve.h"
+%include "GeomAPI_Cylinder.h"
 %include "GeomAPI_DataMapOfShapeMapOfShapes.h"
 %include "GeomAPI_DataMapOfShapeShape.h"
 %include "GeomAPI_Dir.h"
 %include "GeomAPI_Dir2d.h"
 %include "GeomAPI_Edge.h"
+%include "GeomAPI_Ellipse.h"
+%include "GeomAPI_Ellipse2d.h"
 %include "GeomAPI_Face.h"
 %include "GeomAPI_ICustomPrs.h"
 %include "GeomAPI_IPresentable.h"
 %include "GeomAPI_Pnt2d.h"
 %include "GeomAPI_ShapeExplorer.h"
 %include "GeomAPI_ShapeIterator.h"
+%include "GeomAPI_Shell.h"
+%include "GeomAPI_Solid.h"
+%include "GeomAPI_Sphere.h"
+%include "GeomAPI_Torus.h"
+%include "GeomAPI_Trsf.h"
 %include "GeomAPI_Vertex.h"
+%include "GeomAPI_Wire.h"
 %include "GeomAPI_XY.h"
 %include "GeomAPI_XYZ.h"
-%include "GeomAPI_Trsf.h"
-%include "GeomAPI_Wire.h"
-%include "GeomAPI_Shell.h"
-%include "GeomAPI_Solid.h"
-%include "GeomAPI_Box.h"
+
+// std::list -> []
+%template(PointList) std::list<std::shared_ptr<GeomAPI_Pnt> >;
+%template(ShapeList) std::list<std::shared_ptr<GeomAPI_Shape> >;
index e18d4d333e6cb87f05f8ed034a083e00ec945e41..c8344c3acf960bc4a0465d57bb69f87863d8fb0a 100644 (file)
@@ -61,11 +61,19 @@ GeomAPI_Cone::GeomAPI_Cone(const std::shared_ptr<GeomAPI_Pnt>& theLocation,
                            const double theSemiAngle,
                            const double theRadius1,
                            const double theRadius2)
-  : GeomAPI_Interface(
-      newCone(theLocation->impl<gp_Pnt>(), theAxis->impl<gp_Dir>(), theSemiAngle, theRadius1)),
-    myRadius1(theRadius1),
+  : myRadius1(theRadius1),
     myRadius2(theRadius2)
 {
+  gp_Pnt aLoc = theLocation->impl<gp_Pnt>();
+  gp_Dir aDir = theAxis->impl<gp_Dir>();
+  if (theRadius1 > theRadius2) {
+    aLoc.ChangeCoord() += aDir.XYZ() * (theRadius1 - theRadius2) / Tan(theSemiAngle);
+    aDir.Reverse();
+    myRadius1 = theRadius2;
+    myRadius2 = theRadius1;
+  }
+
+  setImpl(newCone(aLoc, aDir, theSemiAngle, myRadius1));
 }
 
 //=================================================================================================
index 270118fcdcfce18498c30e12406839cbab8aaf47..f7ea9c728ae996fa5f344ff5537b98a56d32e869 100644 (file)
@@ -195,15 +195,17 @@ std::shared_ptr<GeomAPI_Cone> GeomAPI_Face::getCone() const
   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
   if (aSurf->IsKind(STANDARD_TYPE(Geom_ConicalSurface))) {
     gp_Cone aCon = Handle(Geom_ConicalSurface)::DownCast(aSurf)->Cone();
-    const gp_Pnt& aLoc = aCon.Location();
-    const gp_Dir& aDir = aCon.Position().Direction();
-    double aRadius1 = aCon.RefRadius();
+    gp_Pnt aLoc = aCon.Location();
+    gp_Dir aDir = aCon.Position().Direction();
 
     double aUMin, aUMax, aVMin, aVMax;
     BRepTools::UVBounds(aFace, aUMin, aUMax, aVMin, aVMax);
 
     double aSemiAngle = Abs(aCon.SemiAngle());
-    double aRadius2 = aRadius1 - (aVMax - aVMin) * Sin(aSemiAngle);
+    double aRadius1 = aCon.RefRadius() + aVMin * Sin(aCon.SemiAngle());
+    double aRadius2 = aCon.RefRadius() + aVMax * Sin(aCon.SemiAngle());
+
+    aLoc.ChangeCoord() += aDir.XYZ() * aVMin * Cos(aCon.SemiAngle());
 
     GeomPointPtr aLocation(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z()));
     GeomDirPtr aDirection(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z()));
index 976d3949f3733bf96dddfe5502494f05f39f8b44..97d66fc6e28ccefb821e4df20a37adb7048e015e 100644 (file)
@@ -85,6 +85,20 @@ bool GeomAPI_Pnt::isEqual(const std::shared_ptr<GeomAPI_Pnt>& theOther) const
   return distance(theOther) < Precision::Confusion();
 }
 
+bool GeomAPI_Pnt::isLess(const std::shared_ptr<GeomAPI_Pnt>& theOther) const
+{
+  if (MY_PNT->X() + Precision::Confusion() < theOther->x())
+    return true;
+  else if (MY_PNT->X() < theOther->x() + Precision::Confusion()) {
+    if (MY_PNT->Y() + Precision::Confusion() < theOther->y())
+      return true;
+    else if (MY_PNT->Y() < theOther->y() + Precision::Confusion() &&
+             MY_PNT->Z() + Precision::Confusion() < theOther->z())
+      return true;
+  }
+  return false;
+}
+
 std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Pnt::to2D(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
   const std::shared_ptr<GeomAPI_Dir>& theDirX, const std::shared_ptr<GeomAPI_Dir>& theDirY)
 {
index 333a2350acf1dfe8c710e469fd0a1015c80a6dde..d06d5d9fb1be8a0a210c697c611be2d8be89ce1a 100644 (file)
@@ -76,6 +76,13 @@ class GeomAPI_Pnt : public GeomAPI_Interface
   GEOMAPI_EXPORT
   bool isEqual(const std::shared_ptr<GeomAPI_Pnt>& theOther) const;
 
+  /// Returns \c true, if the current point is less than theOther.
+  /// The point is less than other, if X coordinate is less.
+  /// In case of X's are equal, if Y is less than other.
+  /// If Y's are equal too, compare Z's.
+  GEOMAPI_EXPORT
+  bool isLess(const std::shared_ptr<GeomAPI_Pnt>& theOther) const;
+
   /// Projects a point to the plane defined by the origin and 2 axes vectors in this plane
   GEOMAPI_EXPORT
   std::shared_ptr<GeomAPI_Pnt2d> to2D(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
index 5b7713a96a4e7f5bae799e120cc4d4fd5229cd51..35a58cc83efacb75ccb6da9d7cd0541c5a852675 100644 (file)
@@ -174,7 +174,7 @@ std::shared_ptr<GeomAPI_Cone> GeomAPI_Shell::getCone() const
 
   GeomPointPtr anApex;
   GeomDirPtr anAxis;
-  double aSemiAngle, aCosSemiAngle;
+  double aSemiAngle, aTanSemiAngle;
   double aHeight1, aHeight2;
 
   for (TopExp_Explorer anExp(impl<TopoDS_Shape>(), TopAbs_FACE); anExp.More(); anExp.Next()) {
@@ -191,9 +191,9 @@ std::shared_ptr<GeomAPI_Cone> GeomAPI_Shell::getCone() const
       anApex = aCurCone->apex();
       anAxis = aCurCone->axis();
       aSemiAngle = aCurCone->semiAngle();
-      aCosSemiAngle = Cos(aSemiAngle);
-      aHeight1 = aCurCone->radius1() * aCosSemiAngle;
-      aHeight2 = aCurCone->radius2() * aCosSemiAngle;
+      aTanSemiAngle = Tan(aSemiAngle);
+      aHeight1 = aCurCone->radius1() / aTanSemiAngle;
+      aHeight2 = aCurCone->radius2() / aTanSemiAngle;
       isFirstFace = false;
     }
     else {
@@ -209,15 +209,15 @@ std::shared_ptr<GeomAPI_Cone> GeomAPI_Shell::getCone() const
 
       double aSign = anAxis->dot(aCurCone->axis());
       double aCurSemiAngle = aCurCone->semiAngle();
-      double aCosCurSemiAngle = Cos(aSemiAngle);
+      double aTanCurSemiAngle = Tan(aSemiAngle);
 
-      double aH = aCurCone->radius1() * aCosCurSemiAngle * aSign;
+      double aH = aCurCone->radius1() / aTanCurSemiAngle * aSign;
       if (aH < aHeight1)
         aHeight1 = aH;
       else if (aH > aHeight2)
         aHeight2 = aH;
 
-      aH = aCurCone->radius2() * aCosCurSemiAngle * aSign;
+      aH = aCurCone->radius2() / aTanCurSemiAngle * aSign;
       if (aH < aHeight1)
         aHeight1 = aH;
       else if (aH > aHeight2)
@@ -229,8 +229,8 @@ std::shared_ptr<GeomAPI_Cone> GeomAPI_Shell::getCone() const
   if (isCone) {
     GeomPointPtr aLocation(new GeomAPI_Pnt(
       anApex->xyz()->added(anAxis->xyz()->multiplied(aHeight1))));
-    double aRadius1 = aHeight1 * Tan(aSemiAngle);
-    double aRadius2 = aHeight2 * Tan(aSemiAngle);
+    double aRadius1 = aHeight1 * aTanSemiAngle;
+    double aRadius2 = aHeight2 * aTanSemiAngle;
 
     aCone = GeomConePtr(new GeomAPI_Cone(aLocation, anAxis, aSemiAngle, aRadius1, aRadius2));
   }
@@ -296,11 +296,25 @@ std::shared_ptr<GeomAPI_Box> GeomAPI_Shell::getParallelepiped() const
     std::list<GeomPointPtr> aCorners;
     if (aWire->isRectangle(aCorners)) {
       // convert rectangle to plane with dimensions
-      GeomPointPtr anOrigin = aCorners.front();
-      aCorners.pop_front();
 
-      GeomPointPtr aFront = aCorners.front();
-      GeomPointPtr aBack = aCorners.back();
+      // find corner with the smallest coordinates
+      std::list<GeomPointPtr>::const_iterator aPrev = --aCorners.end();
+      std::list<GeomPointPtr>::const_iterator aCur = aPrev--;
+      std::list<GeomPointPtr>::const_iterator aNext = aCorners.begin();
+      GeomPointPtr anOrigin = *aCur;
+      GeomPointPtr aFront = *aNext;
+      GeomPointPtr aBack = *aPrev;
+      aPrev = aCur;
+      aCur = aNext++;
+      while (aNext != aCorners.end()) {
+        if ((*aCur)->isLess(anOrigin)) {
+          anOrigin = *aCur;
+          aFront = *aNext;
+          aBack = *aPrev;
+        }
+        aPrev = aCur;
+        aCur = aNext++;
+      }
 
       aPlanes[aNbPlanes].myWidth = aBack->distance(anOrigin);
       aPlanes[aNbPlanes].myDepth = aFront->distance(anOrigin);
index 0f377f2c24f9fbd83f116c1528abd70f5d2d608d..937d74b700fd556cd48968af75a57e1cc06490ce 100644 (file)
@@ -271,8 +271,8 @@ std::shared_ptr<GeomAPI_Cone> GeomAPI_Solid::getCone() const
         anApex->z() + aParam0 * anAxis->z()));
 
     // calculate radii of caps
-    aParam0 /= Cos(aSemiAngle);
-    aParam1 /= Cos(aSemiAngle);
+    aParam0 *= Tan(aSemiAngle);
+    aParam1 *= Tan(aSemiAngle);
 
     aCone = GeomConePtr(new GeomAPI_Cone(aLocation, anAxis, aSemiAngle, aParam0, aParam1));
   }
index 32df6d6bbc55e39207ade979d5e3e2810ec063e2..c840562e6504c6c5c2bbb81f536e524a782263f2 100644 (file)
@@ -81,6 +81,8 @@ bool GeomAPI_Wire::isPolygon(std::list<GeomPointPtr>& thePoints) const
 //==================================================================================================
 bool GeomAPI_Wire::isRectangle(std::list<GeomPointPtr>& thePoints) const
 {
+  thePoints.clear();
+
   const TopoDS_Wire& aWire = TopoDS::Wire(impl<TopoDS_Shape>());
   const Handle(Standard_Type)& aLineType = STANDARD_TYPE(Geom_Line);
 
index a7712b0ed867c6b11ed7ed438e63d9624fa3a43e..e92af5fba156fa400f1086bf9a820a9fffdfd0bf 100644 (file)
@@ -23,6 +23,8 @@
 
   #include "GeomAPI.h"
   #include "GeomAPI_AISObject.h"
+  #include "GeomAPI_Angle.h"
+  #include "GeomAPI_Angle2d.h"
   #include "GeomAPI_Ax1.h"
   #include "GeomAPI_Ax2.h"
   #include "GeomAPI_Ax3.h"
@@ -37,6 +39,8 @@
   #include "GeomAPI_Dir.h"
   #include "GeomAPI_Dir2d.h"
   #include "GeomAPI_Edge.h"
+  #include "GeomAPI_Ellipse.h"
+  #include "GeomAPI_Ellipse2d.h"
   #include "GeomAPI_Face.h"
   #include "GeomAPI_ICustomPrs.h"
   #include "GeomAPI_Interface.h"
   #include "GeomAPI_Solid.h"
   #include "GeomAPI_Sphere.h"
   #include "GeomAPI_Torus.h"
+  #include "GeomAPI_Trsf.h"
   #include "GeomAPI_Vertex.h"
+  #include "GeomAPI_Wire.h"
   #include "GeomAPI_XY.h"
   #include "GeomAPI_XYZ.h"
-  #include "GeomAPI_Trsf.h"
-  #include "GeomAPI_Wire.h"
 
   #include <memory>
   #include <string>
diff --git a/src/GeomAPI/Test/TestBox.py b/src/GeomAPI/Test/TestBox.py
new file mode 100644 (file)
index 0000000..a8412a4
--- /dev/null
@@ -0,0 +1,165 @@
+## Copyright (C) 2018-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from GeomAPI import *
+from SketchAPI import *
+
+from salome.shaper import model
+
+import math
+
+TOLERANCE = 1.e-7
+
+def checkBox(theFeature, theCorner, theWidth, theDepth, theHeight):
+    aShape = theFeature.result().resultSubShapePair()[0].shape()
+    assert(aShape.isSolid())
+    aBox = aShape.solid().getParallelepiped()
+    assert(aBox is not None)
+    assert(aBox.isAxesAligned())
+    aCorner = aBox.corner()
+    assert(aCorner.distance(theCorner) < TOLERANCE), "({}, {}, {}) != expected ({}, {}, {})".format(aCorner.x(), aCorner.y(), aCorner.z(), theCorner.x(), theCorner.y(), theCorner.z())
+    assert(math.fabs(aBox.width() - theWidth) < TOLERANCE), "Width {} != {}".format(aBox.width(), theWidth)
+    assert(math.fabs(aBox.depth() - theDepth) < TOLERANCE), "Depth {} != {}".format(aBox.depth(), theDepth)
+    assert(math.fabs(aBox.height() - theHeight) < TOLERANCE), "Height {} != {}".format(aBox.height(), theHeight)
+
+def assertParallelepiped(theBox, theCorner1, theCorner2):
+    assert(theBox is not None)
+    assert(theBox.isAxesAligned() == False)
+    aCorner1 = theBox.corner()
+    axes = theBox.axes()
+    dirX = axes.dirX()
+    dirY = axes.dirY()
+    dirZ = axes.normal()
+    aCorner2 = GeomAPI.GeomAPI_Pnt(aCorner1.x() + dirX.x() * theBox.width() + dirY.x() * theBox.depth() + dirZ.x() * theBox.height(),
+                                   aCorner1.y() + dirX.y() * theBox.width() + dirY.y() * theBox.depth() + dirZ.y() * theBox.height(),
+                                   aCorner1.z() + dirX.z() * theBox.width() + dirY.z() * theBox.depth() + dirZ.z() * theBox.height())
+    assert(aCorner1.distance(theCorner1) < TOLERANCE), "({}, {}, {}) != expected ({}, {}, {})".format(aCorner1.x(), aCorner1.y(), aCorner1.z(), theCorner1.x(), theCorner1.y(), theCorner1.z())
+    assert(aCorner2.distance(theCorner2) < TOLERANCE), "({}, {}, {}) != expected ({}, {}, {})".format(aCorner2.x(), aCorner2.y(), aCorner2.z(), theCorner2.x(), theCorner2.y(), theCorner2.z())
+
+def checkRotatedBox(theFeature, theCorner1, theCorner2):
+    aShape = theFeature.result().resultSubShapePair()[0].shape()
+    assert(aShape.isSolid())
+    aBox = aShape.solid().getParallelepiped()
+    assertParallelepiped(aBox, theCorner1, theCorner2)
+
+def checkShellRotatedBox(theDocument, theFaceNames, theCorner1, theCorner2):
+    aSelection = []
+    for name in theFaceNames:
+        aSelection.append(model.selection("FACE", name))
+    aShell = model.addShell(theDocument, aSelection)
+    aShape = aShell.result().resultSubShapePair()[0].shape()
+    assert(aShape.isShell())
+    assertParallelepiped(aShape.shell().getParallelepiped(), theCorner1, theCorner2)
+    theDocument.removeFeature(aShell.feature())
+
+def checkShellNotBox(theDocument, theFaceNames):
+    aSelection = []
+    for name in theFaceNames:
+        aSelection.append(model.selection("FACE", name))
+    aShell = model.addShell(theDocument, aSelection)
+    aShape = aShell.result().resultSubShapePair()[0].shape()
+    assert(aShape.isShell())
+    assert(aShape.shell().getParallelepiped() is None)
+    theDocument.removeFeature(aShell.feature())
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamSize = model.addParameter(Part_1_doc, "BoxSize", "10")
+ParamWidth = model.addParameter(Part_1_doc, "Width", "20")
+ParamDepth = model.addParameter(Part_1_doc, "Depth", "10")
+ParamHeight = model.addParameter(Part_1_doc, "Height", "25")
+ParamAngle = model.addParameter(Part_1_doc, "Angle", "30")
+Box_1 = model.addBox(Part_1_doc, "BoxSize", "BoxSize", "BoxSize")
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Top"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "Box_1_1/Front&Box_1_1/Right&Box_1_1/Top"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchLine_1 = Sketch_1.addLine(30, 10, 10, 10)
+SketchLine_2 = Sketch_1.addLine(10, 10, 10, 20)
+SketchLine_3 = Sketch_1.addLine(10, 20, 30, 20)
+SketchLine_4 = Sketch_1.addLine(30, 20, 30, 10)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchPoint_1.result())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), "Width")
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), "Depth")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")], model.selection(), "Height", 0)
+model.do()
+
+# Test 1. Check boxes
+aCornerBox = GeomAPI.GeomAPI_Pnt(0, 0, 0)
+checkBox(Box_1, aCornerBox, ParamSize.value(), ParamSize.value(), ParamSize.value())
+aCornerPara = GeomAPI.GeomAPI_Pnt(ParamSize.value(), ParamSize.value(), ParamSize.value())
+checkBox(Extrusion_1, aCornerPara, ParamWidth.value(), ParamDepth.value(), ParamHeight.value())
+
+# Test 2. Rotate box to keep it still axes-aligned
+Rotation_1 = model.addRotation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1"), 90)
+aCornerPara.setX(aCornerPara.x() + ParamWidth.value() - ParamDepth.value())
+aCornerPara.setY(aCornerPara.y() - ParamWidth.value())
+checkBox(Rotation_1, aCornerPara, ParamDepth.value(), ParamWidth.value(), ParamHeight.value())
+
+# Test 3. Rotate boxes
+Axis_4 = model.addAxis(Part_1_doc, model.selection("VERTEX", "Box_1_1/Back&Box_1_1/Left&Box_1_1/Bottom"), model.selection("VERTEX", "Box_1_1/Front&Box_1_1/Right&Box_1_1/Top"))
+Rotation_2 = model.addRotation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "Axis_1"), "Angle")
+Rotation_3 = model.addRotation(Part_1_doc, [model.selection("SOLID", "Rotation_1_1")], model.selection("EDGE", "Axis_1"), "Angle")
+
+aRotDir = GeomAPI.GeomAPI_Dir(1, 1, 1)
+anAngle = ParamAngle.value() * math.pi / 180.0
+aCosAngle = math.cos(anAngle)
+aSinAngle = math.sin(anAngle)
+
+aCornerBox = GeomAPI.GeomAPI_Pnt(0, ParamSize.value(), 0)
+aCornerBox1 = GeomAPI.GeomAPI_Pnt(ParamSize.value(), 0, ParamSize.value())
+aCornerBox = GeomAPI.GeomAPI_Pnt(aCornerBox.x() * (aCosAngle + (1 - aCosAngle) * aRotDir.x()**2) + aCornerBox.y() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.y() - aSinAngle * aRotDir.z()) + aCornerBox.z() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.z() + aSinAngle * aRotDir.y()),
+                                 aCornerBox.x() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.y() + aSinAngle * aRotDir.z()) + aCornerBox.y() * (aCosAngle + (1 - aCosAngle) * aRotDir.y()**2) + aCornerBox.z() * ((1 - aCosAngle) * aRotDir.y() * aRotDir.z() - aSinAngle * aRotDir.x()),
+                                 aCornerBox.x() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.z() - aSinAngle * aRotDir.y()) + aCornerBox.y() * ((1 - aCosAngle) * aRotDir.y() * aRotDir.z() + aSinAngle * aRotDir.x()) + aCornerBox.z() * (aCosAngle + (1 - aCosAngle) * aRotDir.z()**2))
+aCornerBox1 = GeomAPI.GeomAPI_Pnt(aCornerBox1.x() * (aCosAngle + (1 - aCosAngle) * aRotDir.x()**2) + aCornerBox1.y() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.y() - aSinAngle * aRotDir.z()) + aCornerBox1.z() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.z() + aSinAngle * aRotDir.y()),
+                                  aCornerBox1.x() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.y() + aSinAngle * aRotDir.z()) + aCornerBox1.y() * (aCosAngle + (1 - aCosAngle) * aRotDir.y()**2) + aCornerBox1.z() * ((1 - aCosAngle) * aRotDir.y() * aRotDir.z() - aSinAngle * aRotDir.x()),
+                                  aCornerBox1.x() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.z() - aSinAngle * aRotDir.y()) + aCornerBox1.y() * ((1 - aCosAngle) * aRotDir.y() * aRotDir.z() + aSinAngle * aRotDir.x()) + aCornerBox1.z() * (aCosAngle + (1 - aCosAngle) * aRotDir.z()**2))
+checkRotatedBox(Rotation_2, aCornerBox, aCornerBox1)
+
+aCornerPara.setY(aCornerPara.y() + ParamWidth.value())
+aCornerPara1 = GeomAPI.GeomAPI_Pnt(aCornerPara.x() + ParamDepth.value(), aCornerPara.y() - ParamWidth.value(), aCornerPara.z() + ParamHeight.value())
+aCornerPara = GeomAPI.GeomAPI_Pnt(aCornerPara.x() * (aCosAngle + (1 - aCosAngle) * aRotDir.x()**2) + aCornerPara.y() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.y() - aSinAngle * aRotDir.z()) + aCornerPara.z() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.z() + aSinAngle * aRotDir.y()),
+                                  aCornerPara.x() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.y() + aSinAngle * aRotDir.z()) + aCornerPara.y() * (aCosAngle + (1 - aCosAngle) * aRotDir.y()**2) + aCornerPara.z() * ((1 - aCosAngle) * aRotDir.y() * aRotDir.z() - aSinAngle * aRotDir.x()),
+                                  aCornerPara.x() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.z() - aSinAngle * aRotDir.y()) + aCornerPara.y() * ((1 - aCosAngle) * aRotDir.y() * aRotDir.z() + aSinAngle * aRotDir.x()) + aCornerPara.z() * (aCosAngle + (1 - aCosAngle) * aRotDir.z()**2))
+aCornerPara1 = GeomAPI.GeomAPI_Pnt(aCornerPara1.x() * (aCosAngle + (1 - aCosAngle) * aRotDir.x()**2) + aCornerPara1.y() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.y() - aSinAngle * aRotDir.z()) + aCornerPara1.z() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.z() + aSinAngle * aRotDir.y()),
+                                   aCornerPara1.x() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.y() + aSinAngle * aRotDir.z()) + aCornerPara1.y() * (aCosAngle + (1 - aCosAngle) * aRotDir.y()**2) + aCornerPara1.z() * ((1 - aCosAngle) * aRotDir.y() * aRotDir.z() - aSinAngle * aRotDir.x()),
+                                   aCornerPara1.x() * ((1 - aCosAngle) * aRotDir.x() * aRotDir.z() - aSinAngle * aRotDir.y()) + aCornerPara1.y() * ((1 - aCosAngle) * aRotDir.y() * aRotDir.z() + aSinAngle * aRotDir.x()) + aCornerPara1.z() * (aCosAngle + (1 - aCosAngle) * aRotDir.z()**2))
+checkRotatedBox(Rotation_3, aCornerPara, aCornerPara1)
+
+# Test 4. Compose a non-closed shell of the box faces and check it is not a box
+Shell_objects = ["Rotation_3_1/Rotated_Face_1", "Rotation_3_1/Rotated_Face_2", "Rotation_3_1/Rotated_Face_3", "Rotation_3_1/Rotated_Face_4"]
+checkShellNotBox(Part_1_doc, Shell_objects)
+
+# Test 5. Compose a shell of all box faces
+Shell_objects = ["Rotation_3_1/Rotated_Face_1", "Rotation_3_1/Rotated_Face_2", "Rotation_3_1/Rotated_Face_3", "Rotation_3_1/Rotated_Face_4", "Rotation_3_1/Rotated_Face_5", "Rotation_3_1/Rotated_Face_6"]
+checkShellRotatedBox(Part_1_doc, Shell_objects, aCornerPara, aCornerPara1)
+
+model.end()
diff --git a/src/GeomAPI/Test/TestCone.py b/src/GeomAPI/Test/TestCone.py
new file mode 100644 (file)
index 0000000..2c74a19
--- /dev/null
@@ -0,0 +1,221 @@
+## Copyright (C) 2018-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from GeomAPI import *
+from SketchAPI import *
+
+from salome.shaper import model
+
+import math
+
+TOLERANCE = 1.e-7
+
+def assertCircle(theEdge, theCenter, theRadius):
+    assert(theEdge.isCircle())
+    aCircle = theEdge.circle()
+    assert(aCircle.center().distance(theCenter) < TOLERANCE), "({}, {}, {}) != expected ({}, {}, {})".format(aCircle.center().x(), aCircle.center().y(), aCircle.center().z(), theCenter.x(), theCenter.y(), theCenter.z())
+    assert(math.fabs(aCircle.radius() - theRadius) < TOLERANCE), "Radius {} != {}".format(aCircle.radius(), theRadius)
+
+def checkCircleEdge(theDocument, theEdgeName, theCenter, theRadius):
+    anEdge = model.addEdge(theDocument, [model.selection("EDGE", theEdgeName)])
+    aShape = anEdge.result().resultSubShapePair()[0].shape()
+    assert(aShape.isEdge())
+    assertCircle(aShape.edge(), theCenter, theRadius)
+    theDocument.removeFeature(anEdge.feature())
+
+def checkCircleFace(theDocument, theFaceName, theCenter, theRadius):
+    aFaceFeature = model.addFace(theDocument, [model.selection("FACE", theFaceName)])
+    aShape = aFaceFeature.result().resultSubShapePair()[0].shape()
+    assert(aShape.isFace())
+    aFace = aShape.face();
+    aSubs = aFace.subShapes(GeomAPI.GeomAPI_Shape.EDGE)
+    assert(aSubs.size() == 1)
+    assertCircle(aSubs[0].edge(), theCenter, theRadius)
+    theDocument.removeFeature(aFaceFeature.feature())
+
+def assertEllipse(theEdge, theFirstFocus, theSecondFocus, theMajorRadius, theMinorRadius):
+    assert(theEdge.isEllipse())
+    anEllipse = theEdge.ellipse()
+    assert(anEllipse.firstFocus().distance(theFirstFocus) < TOLERANCE), "({}, {}, {}) != expected ({}, {}, {})".format(anEllipse.firstFocus().x(), anEllipse.firstFocus().y(), anEllipse.firstFocus().z(), theFirstFocus.x(), theFirstFocus.y(), theFirstFocus.z())
+    assert(anEllipse.secondFocus().distance(theSecondFocus) < TOLERANCE), "({}, {}, {}) != expected ({}, {}, {})".format(anEllipse.secondFocus().x(), anEllipse.secondFocus().y(), anEllipse.secondFocus().z(), theSecondFocus.x(), theSecondFocus.y(), theSecondFocus.z())
+    assert(math.fabs(anEllipse.majorRadius() - theMajorRadius) < TOLERANCE), "Major radius {} != {}".format(anEllipse.majorRadius(), theMajorRadius)
+    assert(math.fabs(anEllipse.minorRadius() - theMinorRadius) < TOLERANCE), "Minor radius {} != {}".format(anEllipse.minorRadius(), theMinorRadius)
+
+def checkEllipseEdge(theDocument, theEdgeName, theFirstFocus, theSecondFocus, theMajorRadius, theMinorRadius):
+    anEdge = model.addEdge(theDocument, [model.selection("EDGE", theEdgeName)])
+    aShape = anEdge.result().resultSubShapePair()[0].shape()
+    assert(aShape.isEdge())
+    assertEllipse(aShape.edge(), theFirstFocus, theSecondFocus, theMajorRadius, theMinorRadius)
+    theDocument.removeFeature(anEdge.feature())
+
+def checkEllipseFace(theDocument, theFaceName, theFirstFocus, theSecondFocus, theMajorRadius, theMinorRadius):
+    aFaceFeature = model.addFace(theDocument, [model.selection("FACE", theFaceName)])
+    aShape = aFaceFeature.result().resultSubShapePair()[0].shape()
+    assert(aShape.isFace())
+    aFace = aShape.face();
+    aSubs = aFace.subShapes(GeomAPI.GeomAPI_Shape.EDGE)
+    assert(aSubs.size() == 1)
+    assertEllipse(aSubs[0].edge(), theFirstFocus, theSecondFocus, theMajorRadius, theMinorRadius)
+    theDocument.removeFeature(aFaceFeature.feature())
+
+def assertCone(theCone, theApex, theAxis, theSemiAngle, theRadius1, theRadius2, theHeight):
+    assert(theCone is not None)
+    anApex = theCone.apex()
+    anAxis = theCone.axis()
+    assert(anApex.distance(theApex) < TOLERANCE), "({}, {}, {}) != expected ({}, {}, {})".format(anApex.x(), anApex.y(), anApex.z(), theApex.x(), theApex.y(), theApex.z())
+    assert(anAxis.isParallel(theAxis, TOLERANCE)), "dir({}, {}, {}) is not parallel to dir({}, {}, {})".format(anAxis.x(), anAxis.y(), anAxis.z(), theAxis.x(), theAxis.y(), theAxis.z())
+    assert(math.fabs(theCone.semiAngle() - theSemiAngle) < TOLERANCE), "SemiAngle {} != {}".format(theCone.semiAngle(), theSemiAngle)
+    assert(math.fabs(theCone.radius1() - theRadius1) < TOLERANCE), "Radius1 {} != {}".format(theCone.radius1(), theRadius1)
+    assert(math.fabs(theCone.radius2() - theRadius2) < TOLERANCE), "Radius2 {} != {}".format(theCone.radius2(), theRadius2)
+    assert(math.fabs(theCone.height() - theHeight) < TOLERANCE), "Height {} != {}".format(theCone.height(), theHeight)
+
+def checkConeFace(theDocument, theFaceName, theApex, theAxis, theSemiAngle, theRadius1, theRadius2, theHeight):
+    # check conical face
+    aFace = model.addFace(theDocument, [model.selection("FACE", theFaceName)])
+    aShape = aFace.result().resultSubShapePair()[0].shape()
+    assert(aShape.isFace())
+    assertCone(aShape.face().getCone(), theApex, theAxis, theSemiAngle, theRadius1, theRadius2, theHeight)
+    theDocument.removeFeature(aFace.feature())
+
+def checkConeShell(theDocument, theFaceNames, theApex, theAxis, theSemiAngle, theRadius1, theRadius2, theHeight):
+    # check conical shell
+    aSelection = []
+    for name in theFaceNames:
+        aSelection.append(model.selection("FACE", name))
+    aShell = model.addShell(theDocument, aSelection)
+    aShape = aShell.result().resultSubShapePair()[0].shape()
+    assert(aShape.isShell())
+    assertCone(aShape.shell().getCone(), theApex, theAxis, theSemiAngle, theRadius1, theRadius2, theHeight)
+    theDocument.removeFeature(aShell.feature())
+
+def checkConeAll(theDocument, theFeature, theFaceName, theApex, theAxis, theSemiAngle, theRadius1, theRadius2, theHeight):
+    # check solid
+    aShape = theFeature.result().resultSubShapePair()[0].shape()
+    assert(aShape.isSolid())
+    assertCone(aShape.solid().getCone(), theApex, theAxis, theSemiAngle, theRadius1, theRadius2, theHeight)
+
+    checkConeShell(theDocument, [theFaceName], theApex, theAxis, theSemiAngle, theRadius1, theRadius2, theHeight)
+    checkConeFace(theDocument, theFaceName, theApex, theAxis, theSemiAngle, theRadius1, theRadius2, theHeight)
+
+def checkSegment(theDocument, theEdgeName, theStartPoint, theEndPoint):
+    anEdgeFeature = model.addEdge(theDocument, [model.selection("EDGE", theEdgeName)])
+    aShape = anEdgeFeature.result().resultSubShapePair()[0].shape()
+    assert(aShape.isEdge())
+    anEdge = aShape.edge()
+    assert(anEdge.isLine())
+    assert(anEdge.firstPoint().distance(theStartPoint) < TOLERANCE)
+    assert(anEdge.lastPoint().distance(theEndPoint) < TOLERANCE)
+    theDocument.removeFeature(anEdgeFeature.feature())
+
+def checkVertex(theDocument, theVertexName, theCoordinates):
+    aVertex = model.addVertex(theDocument, [model.selection("VERTEX", theVertexName)])
+    aShape = aVertex.result().resultSubShapePair()[0].shape()
+    assert(aShape.isVertex())
+    assert(aShape.vertex().point().distance(theCoordinates) < TOLERANCE)
+    theDocument.removeFeature(aVertex.feature())
+
+def semiAngle(theRadius1, theRadius2, theHeight):
+    return math.atan(math.fabs(theRadius1 - theRadius2) / theHeight)
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamR1 = model.addParameter(Part_1_doc, "R1", "50")
+ParamR2 = model.addParameter(Part_1_doc, "R2", "5")
+ParamH = model.addParameter(Part_1_doc, "H", "70")
+ParamShift = model.addParameter(Part_1_doc, "Shift", "5")
+ParamAngle = model.addParameter(Part_1_doc, "Angle", "60")
+Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "R1", "R2", "H")
+model.do()
+
+# Test 1. Check cone
+aSemiAngle = semiAngle(ParamR1.value(), ParamR2.value(), ParamH.value())
+anApex = GeomAPI.GeomAPI_Pnt(0, 0, ParamR1.value() / math.tan(aSemiAngle))
+anAxis = GeomAPI.GeomAPI_Dir(0, 0, 1)
+checkConeAll(Part_1_doc, Cone_1, "Cone_1_1/Face_1", anApex, anAxis, aSemiAngle, ParamR2.value(), ParamR1.value(), ParamH.value())
+checkCircleFace(Part_1_doc, "Cone_1_1/Face_2", GeomAPI.GeomAPI_Pnt(0, 0, ParamH.value()), ParamR2.value())
+checkCircleEdge(Part_1_doc, "Cone_1_1/Face_1&Cone_1_1/Face_2", GeomAPI.GeomAPI_Pnt(0, 0, ParamH.value()), ParamR2.value())
+checkCircleFace(Part_1_doc, "Cone_1_1/Face_3", GeomAPI.GeomAPI_Pnt(0, 0, 0), ParamR1.value())
+checkCircleEdge(Part_1_doc, "Cone_1_1/Face_1&Cone_1_1/Face_3", GeomAPI.GeomAPI_Pnt(0, 0, 0), ParamR1.value())
+checkSegment(Part_1_doc, "Cone_1_1/Face_1", GeomAPI.GeomAPI_Pnt(ParamR1.value(), 0, 0), GeomAPI.GeomAPI_Pnt(ParamR2.value(), 0, ParamH.value()))
+
+# Test 2. Update cone radii
+ParamR1.setValue(0)
+model.do()
+aSemiAngle = semiAngle(ParamR1.value(), ParamR2.value(), ParamH.value())
+anApex.setZ(0)
+checkConeAll(Part_1_doc, Cone_1, "Cone_1_1/Face_1", anApex, anAxis, aSemiAngle, ParamR1.value(), ParamR2.value(), ParamH.value())
+checkCircleFace(Part_1_doc, "Cone_1_1/Face_2", GeomAPI.GeomAPI_Pnt(0, 0, ParamH.value()), ParamR2.value())
+checkCircleEdge(Part_1_doc, "Cone_1_1/Face_1&Cone_1_1/Face_2", GeomAPI.GeomAPI_Pnt(0, 0, ParamH.value()), ParamR2.value())
+checkSegment(Part_1_doc, "Cone_1_1/Face_1", GeomAPI.GeomAPI_Pnt(0, 0, 0), GeomAPI.GeomAPI_Pnt(ParamR2.value(), 0, ParamH.value()))
+checkVertex(Part_1_doc, "Cone_1_1/Vertex_2", GeomAPI.GeomAPI_Pnt(0, 0, 0))
+
+ParamR2.setValue(50)
+ParamR1.setValue(10)
+model.do()
+aSemiAngle = semiAngle(ParamR1.value(), ParamR2.value(), ParamH.value())
+anApex.setZ(-ParamR1.value() / math.tan(aSemiAngle))
+checkConeAll(Part_1_doc, Cone_1, "Cone_1_1/Face_1", anApex, anAxis, aSemiAngle, ParamR1.value(), ParamR2.value(), ParamH.value())
+checkCircleFace(Part_1_doc, "Cone_1_1/Face_2", GeomAPI.GeomAPI_Pnt(0, 0, ParamH.value()), ParamR2.value())
+checkCircleEdge(Part_1_doc, "Cone_1_1/Face_1&Cone_1_1/Face_2", GeomAPI.GeomAPI_Pnt(0, 0, ParamH.value()), ParamR2.value())
+checkCircleFace(Part_1_doc, "Cone_1_1/Face_3", GeomAPI.GeomAPI_Pnt(0, 0, 0), ParamR1.value())
+checkCircleEdge(Part_1_doc, "Cone_1_1/Face_1&Cone_1_1/Face_3", GeomAPI.GeomAPI_Pnt(0, 0, 0), ParamR1.value())
+checkSegment(Part_1_doc, "Cone_1_1/Face_1", GeomAPI.GeomAPI_Pnt(ParamR1.value(), 0, 0), GeomAPI.GeomAPI_Pnt(ParamR2.value(), 0, ParamH.value()))
+
+# Test 3. Translate cone
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cone_1_1")], model.selection("EDGE", "PartSet/OX"), "Shift")
+anApex.setX(anApex.x() + ParamShift.value())
+checkConeAll(Part_1_doc, Translation_1, "Translation_1_1/Translated_Face_3", anApex, anAxis, aSemiAngle, ParamR1.value(), ParamR2.value(), ParamH.value())
+checkCircleFace(Part_1_doc, "Translation_1_1/Translated_Face_2", GeomAPI.GeomAPI_Pnt(ParamShift.value(), 0, ParamH.value()), ParamR2.value())
+checkCircleEdge(Part_1_doc, "Translation_1_1/Translated_Face_3&Translation_1_1/Translated_Face_2", GeomAPI.GeomAPI_Pnt(ParamShift.value(), 0, ParamH.value()), ParamR2.value())
+checkCircleFace(Part_1_doc, "Translation_1_1/Translated_Face_1", GeomAPI.GeomAPI_Pnt(ParamShift.value(), 0, 0), ParamR1.value())
+checkCircleEdge(Part_1_doc, "Translation_1_1/Translated_Face_3&Translation_1_1/Translated_Face_1", GeomAPI.GeomAPI_Pnt(ParamShift.value(), 0, 0), ParamR1.value())
+checkSegment(Part_1_doc, "Translation_1_1/Translated_Face_3", GeomAPI.GeomAPI_Pnt(ParamR1.value() + ParamShift.value(), 0, 0), GeomAPI.GeomAPI_Pnt(ParamR2.value() + ParamShift.value(), 0, ParamH.value()))
+
+# Test 4. Rotate cone
+Rotation_1 = model.addRotation(Part_1_doc, [model.selection("SOLID", "Translation_1_1")], model.selection("EDGE", "PartSet/OY"), "Angle")
+anAngle = ParamAngle.value() * math.pi / 180.0
+anAxis = GeomAPI.GeomAPI_Dir(math.sin(anAngle), 0, math.cos(anAngle))
+x, z = anApex.x(), anApex.z()
+anApex.setX(x * math.cos(anAngle) + z * math.sin(anAngle))
+anApex.setZ(-x * math.sin(anAngle) + z * math.cos(anAngle))
+checkConeAll(Part_1_doc, Rotation_1, "Rotation_1_1/Rotated_Face_3", anApex, anAxis, aSemiAngle, ParamR1.value(), ParamR2.value(), ParamH.value())
+aCenter = GeomAPI.GeomAPI_Pnt(ParamShift.value() * math.cos(anAngle) + ParamH.value() * math.sin(anAngle), 0, -ParamShift.value() * math.sin(anAngle) + ParamH.value() * math.cos(anAngle))
+checkCircleFace(Part_1_doc, "Rotation_1_1/Rotated_Face_2", aCenter, ParamR2.value())
+checkCircleEdge(Part_1_doc, "Rotation_1_1/Rotated_Face_3&Rotation_1_1/Rotated_Face_2", aCenter, ParamR2.value())
+aCenter = GeomAPI.GeomAPI_Pnt(ParamShift.value() * math.cos(anAngle), 0, -ParamShift.value() * math.sin(anAngle))
+checkCircleFace(Part_1_doc, "Rotation_1_1/Rotated_Face_1", aCenter, ParamR1.value())
+checkCircleEdge(Part_1_doc, "Rotation_1_1/Rotated_Face_3&Rotation_1_1/Rotated_Face_1", aCenter, ParamR1.value())
+
+# Test 5. Split cone by plane and check conical shell and elliptic face
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), 20, False)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Rotation_1_1"), model.selection("FACE", "Plane_1")])
+checkConeShell(Part_1_doc, ["Partition_1_1_1/Modified_Face_2_2", "Partition_1_1_2/Modified_Face_2_2"], anApex, anAxis, aSemiAngle, ParamR1.value(), ParamR2.value(), ParamH.value())
+
+aFirstFocus = GeomAPI.GeomAPI_Pnt(20, 0, 31.062397266842858)
+aSecondFocus = GeomAPI.GeomAPI_Pnt(20, 0, -1.0935246846933797)
+aMajorRadius = 27.91915871311068
+aMinorRadius = 22.824955511666207
+checkEllipseFace(Part_1_doc, "Partition_1_1_2/Modified_Face_2_1", aFirstFocus, aSecondFocus, aMajorRadius, aMinorRadius)
+checkEllipseEdge(Part_1_doc, "Partition_1_1_1/Modified_Face_1_divided_1_e_1", aFirstFocus, aSecondFocus, aMajorRadius, aMinorRadius)
+
+model.end()
diff --git a/src/GeomAPI/Test/TestCylinder.py b/src/GeomAPI/Test/TestCylinder.py
new file mode 100644 (file)
index 0000000..726b837
--- /dev/null
@@ -0,0 +1,149 @@
+## Copyright (C) 2018-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from GeomAPI import *
+from SketchAPI import *
+
+from salome.shaper import model
+
+import math
+
+TOLERANCE = 1.e-7
+
+def assertCylinder(theCylinder, theLocation, theAxis, theRadius, theHeight):
+    assert(theCylinder is not None)
+    aLoc = theCylinder.location()
+    aDir = theCylinder.axis()
+    assert(aLoc.distance(theLocation) < TOLERANCE), "({}, {}, {}) != expected ({}, {}, {})".format(aLoc.x(), aLoc.y(), aLoc.z(), theLocation.x(), theLocation.y(), theLocation.z())
+    assert(aDir.isParallel(theAxis, TOLERANCE)), "dir({}, {}, {}) is not parallel to dir({}, {}, {})".format(aDir.x(), aDir.y(), aDir.z(), theAxis.x(), theAxis.y(), theAxis.z())
+    assert(math.fabs(theCylinder.radius() - theRadius) < TOLERANCE), "Radius {} != {}".format(theCylinder.radius(), theRadius)
+    assert(math.fabs(theCylinder.height() - theHeight) < TOLERANCE), "Height {} != {}".format(theCylinder.height(), theHeight)
+
+def checkCylinderFace(theDocument, theFaceName, theLocation, theAxis, theRadius, theHeight):
+    aFace = model.addFace(theDocument, [model.selection("FACE", theFaceName)])
+    aShape = aFace.result().resultSubShapePair()[0].shape()
+    assert(aShape.isFace())
+    assertCylinder(aShape.face().getCylinder(), theLocation, theAxis, theRadius, theHeight)
+    theDocument.removeFeature(aFace.feature())
+
+def checkCylinderShell(theDocument, theFaceNames, theLocation, theAxis, theRadius, theHeight):
+    aSelection = []
+    for name in theFaceNames:
+        aSelection.append(model.selection("FACE", name))
+    aShell = model.addShell(theDocument, aSelection)
+    aShape = aShell.result().resultSubShapePair()[0].shape()
+    assert(aShape.isShell())
+    assertCylinder(aShape.shell().getCylinder(), theLocation, theAxis, theRadius, theHeight)
+    theDocument.removeFeature(aShell.feature())
+
+def checkCylinderAll(theDocument, theFeature, theFaceName, theLocation, theAxis, theRadius, theHeight):
+    aShape = theFeature.result().resultSubShapePair()[0].shape()
+    assert(aShape.isSolid())
+    assertCylinder(aShape.solid().getCylinder(), theLocation, theAxis, theRadius, theHeight)
+
+    checkCylinderShell(theDocument, [theFaceName], theLocation, theAxis, theRadius, theHeight)
+    checkCylinderFace(theDocument, theFaceName, theLocation, theAxis, theRadius, theHeight)
+
+def checkNonCylinder(theFeature):
+    aShape = theFeature.result().resultSubShapePair()[0].shape()
+    assert(aShape.isSolid())
+    assert(aShape.solid().getCylinder() is None)
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamH = model.addParameter(Part_1_doc, "H", "10")
+ParamR = model.addParameter(Part_1_doc, "R", "10")
+ParamAngle = model.addParameter(Part_1_doc, "Angle", "30")
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "2*R", "H")
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Cylinder_1_1/Face_2"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "Cylinder_1_1/Face_1&Cylinder_1_1/Face_2__cc"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 10)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "R")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection(), "H", 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("XOZ"))
+SketchLine_1 = Sketch_2.addLine(5, 20, 0, 20)
+SketchLine_2 = Sketch_2.addLine(0, 20, 0, 30)
+SketchLine_3 = Sketch_2.addLine(0, 30, 5, 30)
+SketchLine_4 = Sketch_2.addLine(5, 30, 5, 20)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_2.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_2.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_2.setVertical(SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), "R/2")
+SketchConstraintLength_2 = Sketch_2.setLength(SketchLine_2.result(), "H")
+SketchIntersectionPoint_1 = Sketch_2.addIntersectionPoint(model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), False)
+[SketchPoint_2, SketchPoint_3] = SketchIntersectionPoint_1.intersectionPoints()
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_5 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_5.result())
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")], model.selection("EDGE", "PartSet/OZ"), 270, 0)
+model.do()
+
+# Test 1. Check cylinders
+aLoc1 = GeomAPI.GeomAPI_Pnt(0, 0, 0)
+aLoc2 = GeomAPI.GeomAPI_Pnt(0, 0, 2 * ParamH.value())
+aLoc3 = GeomAPI.GeomAPI_Pnt(0, 0, 3 * ParamH.value())
+anAxis = GeomAPI.GeomAPI_Dir(0, 0, 1)
+checkCylinderAll(Part_1_doc, Cylinder_1, "Cylinder_1_1/Face_1", aLoc1, anAxis, 2 * ParamR.value(), ParamH.value())
+checkCylinderAll(Part_1_doc, Extrusion_1, "Extrusion_1_1/Generated_Face_1", aLoc2, anAxis, ParamR.value(), ParamH.value())
+checkNonCylinder(Revolution_1)
+checkCylinderShell(Part_1_doc, ["Revolution_1_1/Generated_Face_4"], aLoc3, anAxis, 0.5 * ParamR.value(), ParamH.value())
+checkCylinderFace(Part_1_doc, "Revolution_1_1/Generated_Face_4", aLoc3, anAxis, 0.5 * ParamR.value(), ParamH.value())
+
+# Test 2. Rotate cylinders
+Rotation_1 = model.addRotation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OX"), "Angle")
+Rotation_2 = model.addRotation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OX"), "Angle")
+Rotation_3 = model.addRotation(Part_1_doc, [model.selection("SOLID", "Revolution_1_1")], model.selection("EDGE", "PartSet/OX"), "Angle")
+
+anAngle = ParamAngle.value() * math.pi / 180.0
+aCosAngle = math.cos(anAngle)
+aSinAngle = math.sin(anAngle)
+anAxis = GeomAPI.GeomAPI_Dir(0, anAxis.y() * aCosAngle - anAxis.z() * aSinAngle, anAxis.y() * aSinAngle + anAxis.z() * aCosAngle)
+aLoc1 = GeomAPI.GeomAPI_Pnt(0, aLoc1.y() * aCosAngle - aLoc1.z() * aSinAngle, aLoc1.y() * aSinAngle + aLoc1.z() * aCosAngle)
+aLoc2 = GeomAPI.GeomAPI_Pnt(0, aLoc2.y() * aCosAngle - aLoc2.z() * aSinAngle, aLoc2.y() * aSinAngle + aLoc2.z() * aCosAngle)
+aLoc3 = GeomAPI.GeomAPI_Pnt(0, aLoc3.y() * aCosAngle - aLoc3.z() * aSinAngle, aLoc3.y() * aSinAngle + aLoc3.z() * aCosAngle)
+checkCylinderAll(Part_1_doc, Rotation_1, "Rotation_1_1/Rotated_Face_3", aLoc1, anAxis, 2 * ParamR.value(), ParamH.value())
+checkCylinderAll(Part_1_doc, Rotation_2, "Rotation_2_1/Rotated_Face_3", aLoc2, anAxis, ParamR.value(), ParamH.value())
+checkNonCylinder(Rotation_3)
+checkCylinderShell(Part_1_doc, ["Rotation_3_1/Rotated_Face_5"], aLoc3, anAxis, 0.5 * ParamR.value(), ParamH.value())
+checkCylinderFace(Part_1_doc, "Rotation_3_1/Rotated_Face_5", aLoc3, anAxis, 0.5 * ParamR.value(), ParamH.value())
+
+# Test 3. Split cylinder and compose a shell
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOY"), "2.2*H", False)
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), "H", False)
+Partition_1_objects = [model.selection("SOLID", "Rotation_3_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
+
+Shell_1_objects = ["Partition_1_1_1/Modified_Face_3_5", "Partition_1_1_4/Modified_Face_3_3", "Partition_1_1_2/Modified_Face_1_divided_2_1"]
+checkCylinderShell(Part_1_doc, Shell_1_objects, aLoc3, anAxis, 0.5 * ParamR.value(), ParamH.value())
+
+model.end()
diff --git a/src/GeomAPI/Test/TestPolygon.py b/src/GeomAPI/Test/TestPolygon.py
new file mode 100644 (file)
index 0000000..c05c388
--- /dev/null
@@ -0,0 +1,102 @@
+## Copyright (C) 2018-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from GeomAPI import *
+from SketchAPI import *
+
+from salome.shaper import model
+
+import math
+
+TOLERANCE = 1.e-7
+
+def assertRectangle(theWire):
+    assert(theWire is not None)
+    aCorners = [GeomAPI.GeomAPI_Pnt(0, 0, 0)]
+    assert(theWire.isRectangle(aCorners))
+
+def checkRectangleFace(theDocument, theFaceName):
+    aFace = model.addFace(theDocument, [model.selection("FACE", theFaceName)])
+    aShape = aFace.result().resultSubShapePair()[0].shape()
+    assert(aShape.isFace())
+    aSubs = aShape.subShapes(GeomAPI.GeomAPI_Shape.WIRE)
+    assert(aSubs.size() == 1)
+    assertRectangle(aSubs[0].wire())
+    theDocument.removeFeature(aFace.feature())
+
+def checkRectangleWire(theDocument, theEdgeNames):
+    aSelection = []
+    for name in theEdgeNames:
+        aSelection.append(model.selection("EDGE", name))
+    aWire = model.addWire(theDocument, aSelection)
+    aShape = aWire.result().resultSubShapePair()[0].shape()
+    assert(aShape.isWire())
+    assertRectangle(aShape.wire())
+    theDocument.removeFeature(aWire.feature())
+
+
+def assertPolygon(theWire):
+    assert(theWire is not None)
+    aCorners = [GeomAPI.GeomAPI_Pnt(0, 0, 0)]
+    assert(theWire.isPolygon(aCorners))
+
+def checkPolygonWire(theDocument, theEdgeNames):
+    aSelection = []
+    for name in theEdgeNames:
+        aSelection.append(model.selection("EDGE", name))
+    aWire = model.addWire(theDocument, aSelection)
+    aShape = aWire.result().resultSubShapePair()[0].shape()
+    assert(aShape.isWire())
+    assertPolygon(aShape.wire())
+    theDocument.removeFeature(aWire.feature())
+
+def checkPolyline(theDocument, theVertexNames):
+    aSelection = []
+    for name in theVertexNames:
+        aSelection.append(model.selection("VERTEX", name))
+    aWire = model.addPolyline3D(Part_1_doc, aSelection, False)
+    aShape = aWire.result().resultSubShapePair()[0].shape()
+    assert(aShape.isWire())
+    assertPolygon(aShape.wire())
+    theDocument.removeFeature(aWire.feature())
+
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+model.do()
+
+# Test 1. Check face/wire of box is a rectangle
+checkRectangleFace(Part_1_doc, "Box_1_1/Top")
+Wire_edges = ["Box_1_1/Left&Box_1_1/Top", "Box_1_1/Front&Box_1_1/Top", "Box_1_1/Right&Box_1_1/Top", "Box_1_1/Back&Box_1_1/Top"]
+checkRectangleWire(Part_1_doc, Wire_edges)
+
+# Test 2. Build a polygon from edges
+Wire_edges = ["Box_1_1/Left&Box_1_1/Bottom", "Box_1_1/Front&Box_1_1/Left", "Box_1_1/Left&Box_1_1/Top", "Box_1_1/Back&Box_1_1/Top", "Box_1_1/Right&Box_1_1/Top"]
+checkPolygonWire(Part_1_doc, Wire_edges)
+
+# Test 3. Build a polygon from vertices
+Poly_vertices = ["Box_1_1/Back&Box_1_1/Left&Box_1_1/Bottom", "Box_1_1/Front&Box_1_1/Left&Box_1_1/Bottom", "Box_1_1/Front&Box_1_1/Right&Box_1_1/Bottom", "Box_1_1/Front&Box_1_1/Right&Box_1_1/Top", "Box_1_1/Front&Box_1_1/Left&Box_1_1/Top", "Box_1_1/Back&Box_1_1/Right&Box_1_1/Top"]
+checkPolyline(Part_1_doc, Poly_vertices)
+
+model.end()
diff --git a/src/GeomAPI/Test/TestSphere.py b/src/GeomAPI/Test/TestSphere.py
new file mode 100644 (file)
index 0000000..043270f
--- /dev/null
@@ -0,0 +1,125 @@
+## Copyright (C) 2018-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from GeomAPI import *
+from SketchAPI import *
+
+from salome.shaper import model
+
+import math
+
+TOLERANCE = 1.e-7
+
+def checkArc(theDocument, theEdgeName, theCenter, theRadius):
+    # check edge (arc of circle)
+    anEdge = model.addEdge(theDocument, [model.selection("EDGE", theEdgeName)])
+    aShape = anEdge.result().resultSubShapePair()[0].shape()
+    assert(aShape.isEdge())
+    anArcEdge = aShape.edge()
+    assert(anArcEdge.isArc())
+    aCircle = anArcEdge.circle()
+    assert(aCircle.center().distance(theCenter) < TOLERANCE)
+    assert(math.fabs(aCircle.radius() - theRadius) < TOLERANCE)
+    theDocument.removeFeature(anEdge.feature())
+
+def assertSphere(theSphere, theCenter, theRadius):
+    assert(theSphere is not None)
+    assert(theSphere.center().distance(theCenter) < TOLERANCE)
+    assert(math.fabs(theSphere.radius() - theRadius) < TOLERANCE)
+
+def checkSphereFace(theDocument, theFaceName, theCenter, theRadius):
+    # check spherical face
+    aFace = model.addFace(theDocument, [model.selection("FACE", theFaceName)])
+    aShape = aFace.result().resultSubShapePair()[0].shape()
+    assert(aShape.isFace())
+    assertSphere(aShape.face().getSphere(), theCenter, theRadius)
+    theDocument.removeFeature(aFace.feature())
+
+def checkSphereShell(theDocument, theFaceName, theCenter, theRadius):
+    # check spherical shell
+    aShell = model.addShell(theDocument, [model.selection("FACE", theFaceName)])
+    aShape = aShell.result().resultSubShapePair()[0].shape()
+    assert(aShape.isShell())
+    assertSphere(aShape.shell().getSphere(), theCenter, theRadius)
+    theDocument.removeFeature(aShell.feature())
+
+def checkSphereAll(theDocument, theFeature, theFaceName, theCenter, theRadius):
+    # check solid
+    aShape = theFeature.result().resultSubShapePair()[0].shape()
+    assert(aShape.isSolid())
+    assertSphere(aShape.solid().getSphere(), theCenter, theRadius)
+
+    checkSphereShell(theDocument, theFaceName, theCenter, theRadius)
+    checkSphereFace(theDocument, theFaceName, theCenter, theRadius)
+    checkArc(theDocument, theFaceName, theCenter, theRadius)
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamShift = model.addParameter(Part_1_doc, "Shift", "30")
+ParamAngle = model.addParameter(Part_1_doc, "Angle", "30")
+ParamAperture = model.addParameter(Part_1_doc, "Aperture", "360")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_1.addArc(0, 0, 0, -50, 0, 50, False)
+SketchArc_1.results()[1].setColor(225, 0, 0)
+SketchLine_1 = Sketch_1.addLine(0, 50, 0, -50)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_1.endPoint())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchArc_1.center())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], "R")
+model.do()
+
+# Test 1. Compose sphere
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchArc_1_2f-SketchLine_1f")], model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), "Aperture", 0)
+aCenter = GeomAPI.GeomAPI_Pnt(0, 0, 0)
+checkSphereAll(Part_1_doc, Revolution_1, "Revolution_1_1/Generated_Face_2", aCenter, ParamR.value())
+
+# Test 2. Translate sphere
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Revolution_1_1")], model.selection("EDGE", "PartSet/OX"), "Shift")
+aCenter.setX(aCenter.x() + ParamShift.value())
+checkSphereAll(Part_1_doc, Translation_1, "Translation_1_1/Translated_Face_1", aCenter, ParamR.value())
+
+# Test 3. Rotate sphere
+Rotation_1 = model.addRotation(Part_1_doc, [model.selection("SOLID", "Translation_1_1")], model.selection("EDGE", "PartSet/OY"), "Angle")
+anAngle = ParamAngle.value() * math.pi / 180.0
+aCenter.setX(ParamShift.value() * math.cos(anAngle))
+aCenter.setZ(-ParamShift.value() * math.sin(anAngle))
+checkSphereAll(Part_1_doc, Rotation_1, "Rotation_1_1/Rotated_Face_1", aCenter, ParamR.value())
+
+# Test 4. Check result by changing parameters
+ParamR.setValue(100)
+model.do()
+checkSphereAll(Part_1_doc, Rotation_1, "Rotation_1_1/Rotated_Face_1", aCenter, ParamR.value())
+
+ParamAperture.setValue(270)
+model.do()
+checkSphereFace(Part_1_doc, "Rotation_1_1/Rotated_Face_3", aCenter, ParamR.value())
+checkSphereShell(Part_1_doc, "Rotation_1_1/Rotated_Face_3", aCenter, ParamR.value())
+checkArc(Part_1_doc, "Rotation_1_1/Rotated_Face_3&Rotation_1_1/Rotated_Face_1", aCenter, ParamR.value())
+checkArc(Part_1_doc, "Rotation_1_1/Rotated_Face_3&Rotation_1_1/Rotated_Face_2", aCenter, ParamR.value())
+
+model.end()
diff --git a/src/GeomAPI/Test/TestTorus.py b/src/GeomAPI/Test/TestTorus.py
new file mode 100644 (file)
index 0000000..25c7f3e
--- /dev/null
@@ -0,0 +1,95 @@
+## Copyright (C) 2018-20xx  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from GeomAPI import *
+from SketchAPI import *
+
+from salome.shaper import model
+
+import math
+
+TOLERANCE = 1.e-7
+
+def assertTorus(theTorus, theCenter, theAxis, theMajorRadius, theMinorRadius):
+    assert(theTorus is not None)
+    aCenter = theTorus.center()
+    aDir = theTorus.direction()
+    assert(aCenter.distance(theCenter) < TOLERANCE), "({}, {}, {}) != expected ({}, {}, {})".format(aCenter.x(), aCenter.y(), aCenter.z(), theCenter.x(), theCenter.y(), theCenter.z())
+    assert(aDir.isParallel(theAxis, TOLERANCE)), "dir({}, {}, {}) is not parallel to dir({}, {}, {})".format(aDir.x(), aDir.y(), aDir.z(), theAxis.x(), theAxis.y(), theAxis.z())
+    assert(math.fabs(theTorus.majorRadius() - theMajorRadius) < TOLERANCE), "Major radius {} != {}".format(theTorus.majorRadius(), theMajorRadius)
+    assert(math.fabs(theTorus.minorRadius() - theMinorRadius) < TOLERANCE), "Minor radius {} != {}".format(theTorus.minorRadius(), theMinorRadius)
+
+def checkTorusFace(theDocument, theFaceName, theCenter, theAxis, theMajorRadius, theMinorRadius):
+    aFace = model.addFace(theDocument, [model.selection("FACE", theFaceName)])
+    aShape = aFace.result().resultSubShapePair()[0].shape()
+    assert(aShape.isFace())
+    assertTorus(aShape.face().getTorus(), theCenter, theAxis, theMajorRadius, theMinorRadius)
+    theDocument.removeFeature(aFace.feature())
+
+def checkTorusShell(theDocument, theFaceNames, theCenter, theAxis, theMajorRadius, theMinorRadius):
+    aSelection = []
+    for name in theFaceNames:
+        aSelection.append(model.selection("FACE", name))
+    aShell = model.addShell(theDocument, aSelection)
+    aShape = aShell.result().resultSubShapePair()[0].shape()
+    assert(aShape.isShell())
+    assertTorus(aShape.shell().getTorus(), theCenter, theAxis, theMajorRadius, theMinorRadius)
+    theDocument.removeFeature(aShell.feature())
+
+def checkTorusAll(theDocument, theFeature, theFaceName, theCenter, theAxis, theMajorRadius, theMinorRadius):
+    aShape = theFeature.result().resultSubShapePair()[0].shape()
+    assert(aShape.isSolid())
+    assertTorus(aShape.solid().getTorus(), theCenter, theAxis, theMajorRadius, theMinorRadius)
+
+    checkTorusShell(theDocument, [theFaceName], theCenter, theAxis, theMajorRadius, theMinorRadius)
+    checkTorusFace(theDocument, theFaceName, theCenter, theAxis, theMajorRadius, theMinorRadius)
+
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamRMax = model.addParameter(Part_1_doc, "RMax", "15")
+ParamRMin = model.addParameter(Part_1_doc, "RMin", "5")
+ParamAngle = model.addParameter(Part_1_doc, "Angle", "30")
+Torus_1 = model.addTorus(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "RMax", "RMin")
+model.do()
+
+# Test 1. Check torus
+aCenter = GeomAPI.GeomAPI_Pnt(0, 0, 0)
+anAxis = GeomAPI.GeomAPI_Dir(0, 0, 1)
+checkTorusAll(Part_1_doc, Torus_1, "Torus_1_1/Face_1", aCenter, anAxis, ParamRMax.value(), ParamRMin.value())
+
+# Test 2. Rotate torus
+Rotation_1 = model.addRotation(Part_1_doc, [model.selection("SOLID", "Torus_1_1")], model.selection("EDGE", "PartSet/OX"), "Angle")
+anAngle = ParamAngle.value() * math.pi / 180.0
+aCosAngle = math.cos(anAngle)
+aSinAngle = math.sin(anAngle)
+aCenter = GeomAPI.GeomAPI_Pnt(0, aCenter.y() * aCosAngle - aCenter.z() * aSinAngle, aCenter.y() * aSinAngle + aCenter.z() * aCosAngle)
+anAxis = GeomAPI.GeomAPI_Dir(0, anAxis.y() * aCosAngle - anAxis.z() * aSinAngle, anAxis.y() * aSinAngle + anAxis.z() * aCosAngle)
+checkTorusAll(Part_1_doc, Rotation_1, "Rotation_1_1/Rotated_Face_1", aCenter, anAxis, ParamRMax.value(), ParamRMin.value())
+
+# Test 3. Split torus and compose a shell
+Partition_1_objects = [model.selection("SOLID", "Rotation_1_1"), model.selection("FACE", "PartSet/YOZ"), model.selection("FACE", "PartSet/XOZ"), model.selection("FACE", "PartSet/XOY")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
+Shell_1_objects = ["Partition_1_1_6/Modified_Face_4_4", "Partition_1_1_7/Modified_Face_4_3", "Partition_1_1_7/Modified_Face_1_divided_2_1", "Partition_1_1_5/Modified_Face_4_4"]
+checkTorusShell(Part_1_doc, Shell_1_objects, aCenter, anAxis, ParamRMax.value(), ParamRMin.value())
+
+model.end()
index e3032b6244fb6436260ddbb6e082ed6ce3a7255f..7ab81f26c0cfa6f5526a731d4f683a48390e505f 100644 (file)
@@ -25,7 +25,7 @@
 #include <Events_InfoMessage.h>
 
 #include <ModelAPI_AttributeSelection.h>
-#include <ModelAPI_AttributeSelectionList.h>>
+#include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_Feature.h>
 
 bool GeomValidators_NotSelfIntersected::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
@@ -74,17 +74,19 @@ bool GeomValidators_NotSelfIntersected::isValid(const std::shared_ptr<ModelAPI_F
           return false;
         }
 
-        if (aShape->isSelfIntersected()) {
+        if (aShape->isSelfIntersected(4)) {
           theError = "Error: One of selected shapes are self-intersected.";
           return false;
         }
       }
-    }
-    else {
+    } else {
       theError = std::string("Error: validator does not support attribute with type: ")
         + anAttribute->attributeType();
+      return false;
     }
   }
+
+  return true;
 }
 
 bool GeomValidators_NotSelfIntersected::isNotObligatory(std::string /*theFeature*/,
index 09108b4cc24ecb2648838eb3463e01fda924319a..a1951fdd28a64b134c8b29343a47943cd4f49788 100644 (file)
@@ -19,7 +19,6 @@
 ##
 
 INCLUDE(Common)
-INCLUDE(FindPython)
 
 INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events
                     ${PROJECT_SOURCE_DIR}/src/Config
index 3285881c9015a1f19606b9ae520320da95097130..e5113a5c2fea4df2c8dcad75153abfaab8196014 100644 (file)
@@ -30,6 +30,9 @@
 
 %{
   #include "ModelAPI_swig.h"
+
+  // fix for SWIG v2.0.4
+  #define SWIGPY_SLICE_ARG(obj) ((PyObject*)(obj))
 %}
 
 // import other modules
index b99e1d4ebabe7357c48008869f01e960710031fa..fa8a77159e5bff3469b4e816fa4e245c5359f3eb 100644 (file)
@@ -92,7 +92,7 @@ ModuleBase_WidgetIntValue::ModuleBase_WidgetIntValue(QWidget* theParent,
   }
 
   myDefVal = QString::fromStdString(getDefaultValue()).toInt(&myHasDefault);
-  if (isOk)
+  if (myHasDefault)
     mySpinBox->setValue(myDefVal);
 
   QString aTTip = translate(theData->widgetTooltip());
@@ -199,7 +199,7 @@ bool ModuleBase_WidgetIntValue::restoreValueCustom()
     ModuleBase_Tools::setSpinText(mySpinBox, aText);
   } else {
     ModuleBase_Tools::setSpinValue(mySpinBox,
-      anAttribute->isInitialized() ? anAttribute->value() : 0);
+      anAttribute->isInitialized() ? anAttribute->value() : myDefVal);
     if (anAttribute->isInitialized() && anAttribute->expressionInvalid()) {
       anAttribute->setExpressionError("");
       anAttribute->setExpressionInvalid(false);
index 72e0ef18176ef33f4d593a26c5ce53f34145c5b7..82656539a5888d17bff8288200514acb204ae368 100644 (file)
@@ -623,7 +623,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
                          label="Angle"
                          icon="icons/Sketch/angle.png"
                          tooltip="Rotation angle"
-                         default="270" min="0" max="360"
+                         default="360" min="0" max="360"
                          use_reset="false">
               <validator id="SketchPlugin_MultiRotationAngleValidator" />
             </doublevalue>
@@ -638,7 +638,7 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
                          label="Angle"
                          icon="icons/Sketch/angle.png"
                          tooltip="Rotation angle"
-                         default="270" min="0" max="360"
+                         default="90" min="0" max="360"
                          use_reset="false">
               <validator id="SketchPlugin_MultiRotationAngleValidator" />
             </doublevalue>