From: mpv Date: Wed, 5 Sep 2018 07:41:22 +0000 (+0300) Subject: Correction for the RC1 version from the current master version. X-Git-Tag: SHAPER_V9_1_0RC2 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=dac34b4bb3af6115b63c3eb46f111fdaa313316c;p=modules%2Fshaper.git Correction for the RC1 version from the current master version. --- diff --git a/env.sh b/env.sh index 7091b84af..2edade92e 100644 --- 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 diff --git a/env_linux.sh b/env_linux.sh index 5beff47b4..d6cf38269 100644 --- a/env_linux.sh +++ b/env_linux.sh @@ -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} diff --git a/env_salome.sh b/env_salome.sh index ccaf3aebc..60752255b 100644 --- a/env_salome.sh +++ b/env_salome.sh @@ -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 diff --git a/src/ExchangeAPI/ExchangeAPI_Export.cpp b/src/ExchangeAPI/ExchangeAPI_Export.cpp index 492479e50..6165c8fa6 100644 --- a/src/ExchangeAPI/ExchangeAPI_Export.cpp +++ b/src/ExchangeAPI/ExchangeAPI_Export.cpp @@ -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; } } diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 11a8377a2..1bb74ed46 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -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 index 000000000..e584a531f --- /dev/null +++ b/src/FeaturesPlugin/boolean_fill_widget.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index bb13f70af..3858a8811 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -94,7 +94,7 @@ email : webmaster.salome@opencascade.com - + diff --git a/src/GeomAPI/CMakeLists.txt b/src/GeomAPI/CMakeLists.txt index 82b062a0c..4959dde28 100644 --- a/src/GeomAPI/CMakeLists.txt +++ b/src/GeomAPI/CMakeLists.txt @@ -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 +) diff --git a/src/GeomAPI/GeomAPI.i b/src/GeomAPI/GeomAPI.i index 82e292108..aa2648245 100644 --- a/src/GeomAPI/GeomAPI.i +++ b/src/GeomAPI/GeomAPI.i @@ -29,22 +29,30 @@ // 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) @@ -58,31 +66,65 @@ %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 > &thePoints (std::list > temp) { + std::shared_ptr * 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 *), 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" @@ -94,11 +136,16 @@ %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 >; +%template(ShapeList) std::list >; diff --git a/src/GeomAPI/GeomAPI_Cone.cpp b/src/GeomAPI/GeomAPI_Cone.cpp index e18d4d333..c8344c3ac 100644 --- a/src/GeomAPI/GeomAPI_Cone.cpp +++ b/src/GeomAPI/GeomAPI_Cone.cpp @@ -61,11 +61,19 @@ GeomAPI_Cone::GeomAPI_Cone(const std::shared_ptr& theLocation, const double theSemiAngle, const double theRadius1, const double theRadius2) - : GeomAPI_Interface( - newCone(theLocation->impl(), theAxis->impl(), theSemiAngle, theRadius1)), - myRadius1(theRadius1), + : myRadius1(theRadius1), myRadius2(theRadius2) { + gp_Pnt aLoc = theLocation->impl(); + gp_Dir aDir = theAxis->impl(); + if (theRadius1 > theRadius2) { + aLoc.ChangeCoord() += aDir.XYZ() * (theRadius1 - theRadius2) / Tan(theSemiAngle); + aDir.Reverse(); + myRadius1 = theRadius2; + myRadius2 = theRadius1; + } + + setImpl(newCone(aLoc, aDir, theSemiAngle, myRadius1)); } //================================================================================================= diff --git a/src/GeomAPI/GeomAPI_Face.cpp b/src/GeomAPI/GeomAPI_Face.cpp index 270118fcd..f7ea9c728 100644 --- a/src/GeomAPI/GeomAPI_Face.cpp +++ b/src/GeomAPI/GeomAPI_Face.cpp @@ -195,15 +195,17 @@ std::shared_ptr 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())); diff --git a/src/GeomAPI/GeomAPI_Pnt.cpp b/src/GeomAPI/GeomAPI_Pnt.cpp index 976d3949f..97d66fc6e 100644 --- a/src/GeomAPI/GeomAPI_Pnt.cpp +++ b/src/GeomAPI/GeomAPI_Pnt.cpp @@ -85,6 +85,20 @@ bool GeomAPI_Pnt::isEqual(const std::shared_ptr& theOther) const return distance(theOther) < Precision::Confusion(); } +bool GeomAPI_Pnt::isLess(const std::shared_ptr& 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_Pnt::to2D(const std::shared_ptr& theOrigin, const std::shared_ptr& theDirX, const std::shared_ptr& theDirY) { diff --git a/src/GeomAPI/GeomAPI_Pnt.h b/src/GeomAPI/GeomAPI_Pnt.h index 333a2350a..d06d5d9fb 100644 --- a/src/GeomAPI/GeomAPI_Pnt.h +++ b/src/GeomAPI/GeomAPI_Pnt.h @@ -76,6 +76,13 @@ class GeomAPI_Pnt : public GeomAPI_Interface GEOMAPI_EXPORT bool isEqual(const std::shared_ptr& 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& theOther) const; + /// Projects a point to the plane defined by the origin and 2 axes vectors in this plane GEOMAPI_EXPORT std::shared_ptr to2D(const std::shared_ptr& theOrigin, diff --git a/src/GeomAPI/GeomAPI_Shell.cpp b/src/GeomAPI/GeomAPI_Shell.cpp index 5b7713a96..35a58cc83 100644 --- a/src/GeomAPI/GeomAPI_Shell.cpp +++ b/src/GeomAPI/GeomAPI_Shell.cpp @@ -174,7 +174,7 @@ std::shared_ptr GeomAPI_Shell::getCone() const GeomPointPtr anApex; GeomDirPtr anAxis; - double aSemiAngle, aCosSemiAngle; + double aSemiAngle, aTanSemiAngle; double aHeight1, aHeight2; for (TopExp_Explorer anExp(impl(), TopAbs_FACE); anExp.More(); anExp.Next()) { @@ -191,9 +191,9 @@ std::shared_ptr 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_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_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_Shell::getParallelepiped() const std::list 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::const_iterator aPrev = --aCorners.end(); + std::list::const_iterator aCur = aPrev--; + std::list::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); diff --git a/src/GeomAPI/GeomAPI_Solid.cpp b/src/GeomAPI/GeomAPI_Solid.cpp index 0f377f2c2..937d74b70 100644 --- a/src/GeomAPI/GeomAPI_Solid.cpp +++ b/src/GeomAPI/GeomAPI_Solid.cpp @@ -271,8 +271,8 @@ std::shared_ptr 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)); } diff --git a/src/GeomAPI/GeomAPI_Wire.cpp b/src/GeomAPI/GeomAPI_Wire.cpp index 32df6d6bb..c840562e6 100644 --- a/src/GeomAPI/GeomAPI_Wire.cpp +++ b/src/GeomAPI/GeomAPI_Wire.cpp @@ -81,6 +81,8 @@ bool GeomAPI_Wire::isPolygon(std::list& thePoints) const //================================================================================================== bool GeomAPI_Wire::isRectangle(std::list& thePoints) const { + thePoints.clear(); + const TopoDS_Wire& aWire = TopoDS::Wire(impl()); const Handle(Standard_Type)& aLineType = STANDARD_TYPE(Geom_Line); diff --git a/src/GeomAPI/GeomAPI_swig.h b/src/GeomAPI/GeomAPI_swig.h index a7712b0ed..e92af5fba 100644 --- a/src/GeomAPI/GeomAPI_swig.h +++ b/src/GeomAPI/GeomAPI_swig.h @@ -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" @@ -54,11 +58,11 @@ #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 #include diff --git a/src/GeomAPI/Test/TestBox.py b/src/GeomAPI/Test/TestBox.py new file mode 100644 index 000000000..a8412a4cd --- /dev/null +++ b/src/GeomAPI/Test/TestBox.py @@ -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 +## + +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 index 000000000..2c74a1955 --- /dev/null +++ b/src/GeomAPI/Test/TestCone.py @@ -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 +## + +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 index 000000000..726b837fa --- /dev/null +++ b/src/GeomAPI/Test/TestCylinder.py @@ -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 +## + +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 index 000000000..c05c38864 --- /dev/null +++ b/src/GeomAPI/Test/TestPolygon.py @@ -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 +## + +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 index 000000000..043270f6f --- /dev/null +++ b/src/GeomAPI/Test/TestSphere.py @@ -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 +## + +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 index 000000000..25c7f3edc --- /dev/null +++ b/src/GeomAPI/Test/TestTorus.py @@ -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 +## + +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() diff --git a/src/GeomValidators/GeomValidators_NotSelfIntersected.cpp b/src/GeomValidators/GeomValidators_NotSelfIntersected.cpp index e3032b624..7ab81f26c 100644 --- a/src/GeomValidators/GeomValidators_NotSelfIntersected.cpp +++ b/src/GeomValidators/GeomValidators_NotSelfIntersected.cpp @@ -25,7 +25,7 @@ #include #include -#include > +#include #include bool GeomValidators_NotSelfIntersected::isValid(const std::shared_ptr& theFeature, @@ -74,17 +74,19 @@ bool GeomValidators_NotSelfIntersected::isValid(const std::shared_ptrisSelfIntersected()) { + 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*/, diff --git a/src/InitializationPlugin/CMakeLists.txt b/src/InitializationPlugin/CMakeLists.txt index 09108b4cc..a1951fdd2 100644 --- a/src/InitializationPlugin/CMakeLists.txt +++ b/src/InitializationPlugin/CMakeLists.txt @@ -19,7 +19,6 @@ ## INCLUDE(Common) -INCLUDE(FindPython) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events ${PROJECT_SOURCE_DIR}/src/Config diff --git a/src/ModelAPI/ModelAPI.i b/src/ModelAPI/ModelAPI.i index 3285881c9..e5113a5c2 100644 --- a/src/ModelAPI/ModelAPI.i +++ b/src/ModelAPI/ModelAPI.i @@ -30,6 +30,9 @@ %{ #include "ModelAPI_swig.h" + + // fix for SWIG v2.0.4 + #define SWIGPY_SLICE_ARG(obj) ((PyObject*)(obj)) %} // import other modules diff --git a/src/ModuleBase/ModuleBase_WidgetIntValue.cpp b/src/ModuleBase/ModuleBase_WidgetIntValue.cpp index b99e1d4eb..fa8a77159 100644 --- a/src/ModuleBase/ModuleBase_WidgetIntValue.cpp +++ b/src/ModuleBase/ModuleBase_WidgetIntValue.cpp @@ -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); diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 72e0ef181..82656539a 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -623,7 +623,7 @@ email : webmaster.salome@opencascade.com @@ -638,7 +638,7 @@ email : webmaster.salome@opencascade.com