From 87533ec02b1e1d85e797013ee7c377b2b25801be Mon Sep 17 00:00:00 2001 From: skv Date: Thu, 12 Feb 2015 16:59:30 +0300 Subject: [PATCH] 0022776: [CEA 1269] Project a wire or a face on a cylinder --- .../transformation_operations_ex07.py | 16 + .../gui/GEOM/images/proj_on_cyl_dlg.png | Bin 0 -> 25225 bytes .../gui/GEOM/images/proj_on_cyl_preview.png | Bin 0 -> 3218 bytes .../projection_on_cylinder_operation.doc | 40 ++ .../GEOM/input/transformation_operations.doc | 1 + doc/salome/gui/GEOM/input/tui_test_all.doc | 2 +- idl/GEOM_Gen.idl | 25 ++ resources/CMakeLists.txt | 1 + resources/proj_on_cyl.png | Bin 0 -> 764 bytes src/GEOMGUI/GEOM_images.ts | 8 + src/GEOMGUI/GEOM_msg_en.ts | 31 ++ src/GEOMGUI/GeometryGUI.cxx | 4 + src/GEOMGUI/GeometryGUI_Operations.h | 1 + src/GEOMImpl/CMakeLists.txt | 1 + src/GEOMImpl/GEOMImpl_IProjOnCyl.hxx | 61 +++ .../GEOMImpl_ITransformOperations.cxx | 76 ++++ .../GEOMImpl_ITransformOperations.hxx | 6 + src/GEOMImpl/GEOMImpl_ProjectionDriver.cxx | 303 +++++++++++++- src/GEOMImpl/GEOMImpl_ProjectionDriver.hxx | 10 + src/GEOMImpl/GEOMImpl_Types.hxx | 5 +- src/GEOMUtils/CMakeLists.txt | 6 + src/GEOMUtils/GEOMUtils_HTrsfCurve2d.cxx | 51 +++ src/GEOMUtils/GEOMUtils_HTrsfCurve2d.hxx | 84 ++++ src/GEOMUtils/GEOMUtils_Trsf2d.cxx | 110 +++++ src/GEOMUtils/GEOMUtils_Trsf2d.hxx | 134 ++++++ src/GEOMUtils/GEOMUtils_TrsfCurve2d.cxx | 382 ++++++++++++++++++ src/GEOMUtils/GEOMUtils_TrsfCurve2d.hxx | 242 +++++++++++ src/GEOM_I/GEOM_ITransformOperations_i.cc | 34 ++ src/GEOM_I/GEOM_ITransformOperations_i.hh | 5 + src/GEOM_SWIG/GEOM_TestAll.py | 2 + src/GEOM_SWIG/geomBuilder.py | 61 +++ src/TransformationGUI/CMakeLists.txt | 3 + src/TransformationGUI/TransformationGUI.cxx | 4 + .../TransformationGUI_ProjectionOnCylDlg.cxx | 360 +++++++++++++++++ .../TransformationGUI_ProjectionOnCylDlg.h | 78 ++++ 35 files changed, 2143 insertions(+), 4 deletions(-) create mode 100644 doc/salome/gui/GEOM/images/proj_on_cyl_dlg.png create mode 100644 doc/salome/gui/GEOM/images/proj_on_cyl_preview.png create mode 100644 doc/salome/gui/GEOM/input/projection_on_cylinder_operation.doc create mode 100644 resources/proj_on_cyl.png create mode 100644 src/GEOMImpl/GEOMImpl_IProjOnCyl.hxx create mode 100644 src/GEOMUtils/GEOMUtils_HTrsfCurve2d.cxx create mode 100644 src/GEOMUtils/GEOMUtils_HTrsfCurve2d.hxx create mode 100644 src/GEOMUtils/GEOMUtils_Trsf2d.cxx create mode 100644 src/GEOMUtils/GEOMUtils_Trsf2d.hxx create mode 100644 src/GEOMUtils/GEOMUtils_TrsfCurve2d.cxx create mode 100644 src/GEOMUtils/GEOMUtils_TrsfCurve2d.hxx create mode 100644 src/TransformationGUI/TransformationGUI_ProjectionOnCylDlg.cxx create mode 100644 src/TransformationGUI/TransformationGUI_ProjectionOnCylDlg.h diff --git a/doc/salome/examples/transformation_operations_ex07.py b/doc/salome/examples/transformation_operations_ex07.py index f76bd9036..d323cf0b7 100644 --- a/doc/salome/examples/transformation_operations_ex07.py +++ b/doc/salome/examples/transformation_operations_ex07.py @@ -38,3 +38,19 @@ prj = geompy.MakeProjection(v1, w1) geompy.addToStudy(w1, "w1") geompy.addToStudy(v1, "v1") geompy.addToStudy(prj, "projOnWire") + +#projection of a wire on cylinder +pp1 = geompy.MakeVertex(100, 200, 0) +pp2 = geompy.MakeVertex(100, 200, 80) +pp3 = geompy.MakeVertex(100, 220, 90) +pp4 = geompy.MakeVertex(100, 130, 80) +pp5 = geompy.MakeVertex(100, 90, 80) +cc1 = geompy.MakeInterpol([pp1, pp2, pp3, pp4, pp5], True, False) +ww1 = geompy.MakeWire([cc1], 1.e-7) +vx = geompy.MakeVectorDXDYDZ(100, 0, 0) +pln1 = geompy.MakePlane(pp1, vx, 200) +face1 = geompy.MakeFaceFromSurface(pln1, ww1) +prj_cyl = geompy.MakeProjectionOnCylinder(face1, 100) + +geompy.addToStudy(face1, "pln_face") +geompy.addToStudy(prj_cyl, "projOnCylinder") diff --git a/doc/salome/gui/GEOM/images/proj_on_cyl_dlg.png b/doc/salome/gui/GEOM/images/proj_on_cyl_dlg.png new file mode 100644 index 0000000000000000000000000000000000000000..38d81b51e0461caac799cb46997592cb84b20fa2 GIT binary patch literal 25225 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/input/projection_on_cylinder_operation.doc b/doc/salome/gui/GEOM/input/projection_on_cylinder_operation.doc new file mode 100644 index 000000000..be0c5aa27 --- /dev/null +++ b/doc/salome/gui/GEOM/input/projection_on_cylinder_operation.doc @@ -0,0 +1,40 @@ +/*! + +\page projection_on_cylinder_operation_page Projection on Cylinder + +\n To produce a Projection on Cylinder in the Main Menu select +Operations - > Transformation - > Projection on Cylinder + +\n This operation makes a projection of a Source planar wire or face on +a cylinder defined by its radius. The cylinder's coordinate system is +the same as the global coordinate system. The result represents a wire or +a face that represents a projection of the source shape onto a cylinder. + +To make a projection it is necessary to define: +- \b Object to be projected. It can be either a planar wire or a face; +- \b Radius of the cylinder; +- Starting angle from the cylinder's X axis around Z axis. This is +the angle of the projection starting. +- Length angle in which to project the total length of +the wire. If it is unchecked the projection is not scaled and natural +wire length is kept for the projection. + +\ref restore_presentation_parameters_page "Advanced options". + +\image html proj_on_cyl_dlg.png + +\n Example: + +\image html proj_on_cyl_preview.png "The curve (in red) and its projection on the cylinder" + +\n TUI Command: geompy.MakeProjectionOnCylinder(theObject, theRadius, +theStartAngle=0.0, theAngleLength=-1.0), +where \em theObject is a shape which has to be projected, \em theRadius +is a cylinder radius, \em theStartAngle the starting angle of projection in +radians, \em theAngleLength the projection length angle in radians. +The \em Result will be a \em GEOM_Object. + +Our TUI Scripts provide you with useful examples of the use of +\ref tui_projection "Transformation Operations". + +*/ diff --git a/doc/salome/gui/GEOM/input/transformation_operations.doc b/doc/salome/gui/GEOM/input/transformation_operations.doc index ac745b669..6ce6395ce 100644 --- a/doc/salome/gui/GEOM/input/transformation_operations.doc +++ b/doc/salome/gui/GEOM/input/transformation_operations.doc @@ -17,6 +17,7 @@ which allow to:
  • Create an \subpage offset_operation_page "Offset" of an object.
  • Create a \subpage projection_operation_page "Projection" of an object on a face.
  • Create an \subpage extension_operation_page "Extension" of an edge or a face.
  • +
  • Create a \subpage projection_on_cylinder_operation_page "Projection on cylinder".
  • Create a simultaneous \subpage multi_translation_operation_page "Translation in several directions".
  • Create a simultaneous \subpage multi_rotation_operation_page
  • "Rotation in several directions". diff --git a/doc/salome/gui/GEOM/input/tui_test_all.doc b/doc/salome/gui/GEOM/input/tui_test_all.doc index b1f915ea2..f2407ca29 100644 --- a/doc/salome/gui/GEOM/input/tui_test_all.doc +++ b/doc/salome/gui/GEOM/input/tui_test_all.doc @@ -61,7 +61,7 @@ \until Scale4 \anchor swig_all_trsf_more -\until MakeProjectionOnWire +\until MakeProjectionOnCylinder \anchor swig_ChangeOrientation \until ChangeOrientation diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 9bdfda2b2..eaea44370 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -1420,6 +1420,31 @@ module GEOM * \return theObject. */ GEOM_Object RecomputeObject (in GEOM_Object theObject); + + /*! + * \brief Compute the projection of a wire or a face on a cylinder. + * + * This method computes a wire or a face or a compound of faces + * that represents a projection of the source shape onto cylinder. + * The cylinder's coordinate system is the same as the global coordinate + * system. + * + * \param theObject The object to be projected. It can be either + * a planar wire or a face. + * \param theRadius The radius of the cylinder. + * \param theStartAngle The starting angle from the cylinder's X axis + * around Z axis. The angle from which the projection is started. + * \param theAngleLength The projection length angle. The angle in which + * to project the total length of the wire. If it is negative the + * projection is not scaled and natural wire length is kept for + * the projection. + * \return A wire or a face or a compound of faces that represents a + * projection of the source shape onto a cylinder. + */ + GEOM_Object MakeProjectionOnCylinder (in GEOM_Object theObject, + in double theRadius, + in double theStartAngle, + in double theAngleLength); }; /*! diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 3a1bb3200..cef2c42f2 100755 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -134,6 +134,7 @@ SET( _res_files projection.png projection_on_edge.png projection_on_wire.png + proj_on_cyl.png origin_and_vectors.png partition.png partitionkeep.png diff --git a/resources/proj_on_cyl.png b/resources/proj_on_cyl.png new file mode 100644 index 0000000000000000000000000000000000000000..bd52b718831d99152061ce2253d17bd5eff9f5a9 GIT binary patch literal 764 zcmVPx#24YJ`L;(K)UjSdP6ImMo000SaNLh0L01FZT01FZU(%pXi00007bV*G`2j2n= z4+S=+JI-SO00MkTL_t(I%Y~FXXcSQthQEE-329TL5Yxmav9U6RB4LfuCJ|IrBz8h1 zU}7bP81NCb)6`m6h!{~2aSI{Bc8ZU}PAefK1UBr>W9L4PMP`@X%w|0>%*?&_eE0mE zM~*HwKR+)3-g~sxL{UT-hJ;~A5Cl{zl^lCmvHfReW=4v|A_tFM1;BX$pcZLjWp|#$ zvc7&rf*@dPYbyh8Elf{O%aN&@9h=Te1{Ntxlvn`XE{p-}2ck@b#u&b=J|dsbGc-Pn zh+v#2R+ff#9kBOH<5+8(u7`miO=t_KwPt8yj$97Dt=`94i!p{Mil|nrRI63$^*Xg$ zjia-#a4Mqm^fJIGumSw(04k->)*~Veo}9yakF}ofFK=<^{9}UH5GjjM2~I^=9XDP3 zQ`uyI$~e3T&I#6gN{f>m2l#aXfQJ`Xa4N>?7^fS(vz#PJYq6m%+Ij#^l}Z47D3`HG z)B-u9djpkH)MJfvLZQ&T%$hJA*Kp=P5gKD~en)Cz1d~RXftm*59pYWr{d_ynI*;>$ z^MV)292RjY%p%V9j_}^*CM=%=;Mw&TT_bcx;dH{?&nszu`jPu>6vw@LIRkD=Rf^K^2oeTJ7_=_vDS2{xn>Xch7N|9%6rvMEX?&tu zk?oe7DVwD;i#U_O#|QMXYX?R_1U6QCOU@VeA=YsF#0{Kj;B*7isN;;n8--8HB_~3z zQ0RJDdj*fAQ-k5Dg|xkPq^Y2acN*~?MELvlUDIbR^?45b+zlKA&Zg7jG`(#teTP5= uc%7Lx=?JQ{eRoWeT^6Qiey2XI?EC|R`LFFD53h{?0000g+&7Z literal 0 HcmV?d00001 diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index 489aaa5aa..1e906fe81 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -463,6 +463,10 @@ ICON_DLG_EXTEND_FACE faceextension.png + + ICO_DLG_PROJ_ON_CYL + proj_on_cyl.png + ICON_DLG_PARTITION partition.png @@ -1155,6 +1159,10 @@ ICO_EXTENSION edgeextension.png + + ICO_PROJ_ON_CYL + proj_on_cyl.png + ICO_ORIGIN_AND_VECTORS origin_and_vectors.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index 4da50d2e7..5142eb365 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -1260,6 +1260,10 @@ Please, select face, shell or solid and try again GEOM_PROJECTION_TITLE Projection + + GEOM_PROJECTION_NAME + Projection + GEOM_PROJ_ON_FACE_SOURCE Source vertex, edge or wire @@ -2844,6 +2848,10 @@ Please, select face, shell or solid and try again MEN_PROJECTION Projection + + MEN_PROJ_ON_CYL + Projection on Cylinder + MEN_OPERATIONS Operations @@ -3804,6 +3812,10 @@ Please, select face, shell or solid and try again STB_PROJECTION Project a point, an edge or a wire on a face + + STB_PROJ_ON_CYL + Project a wire or a face on a cylinder + STB_ORIGIN_AND_VECTORS Create an origin and base Vectors @@ -4424,6 +4436,10 @@ Please, select face, shell or solid and try again TOP_PROJECTION Projection + + TOP_PROJ_ON_CYL + Projection on Cylinder + TOP_ORIGIN_AND_VECTORS Create an origin and base Vectors @@ -7404,4 +7420,19 @@ Do you want to create new material? Materials: %1 of %2 + + TransformationGUI_ProjectionOnCylDlg + + GEOM_PROJ_ON_CYL_TITLE + Projection On A Cylinder + + + GEOM_PROJ_ON_CYL_START_ANGLE + Starting angle + + + GEOM_PROJ_ON_CYL_LENGTH_ANGLE + Length angle + + diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index 143f63b05..3e90cd95a 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -587,6 +587,7 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam ) case GEOMOp::OpScale: // MENU TRANSFORMATION - SCALE case GEOMOp::OpOffset: // MENU TRANSFORMATION - OFFSET case GEOMOp::OpProjection: // MENU TRANSFORMATION - PROJECTION + case GEOMOp::OpProjOnCyl: // MENU TRANSFORMATION - PROJECTION ON CYLINDER case GEOMOp::OpMultiTranslate: // MENU TRANSFORMATION - MULTI-TRANSLATION case GEOMOp::OpMultiRotate: // MENU TRANSFORMATION - MULTI-ROTATION case GEOMOp::OpReimport: // CONTEXT(POPUP) MENU - RELOAD_IMPORTED @@ -966,6 +967,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpScale, "SCALE" ); createGeomAction( GEOMOp::OpOffset, "OFFSET" ); createGeomAction( GEOMOp::OpProjection, "PROJECTION" ); + createGeomAction( GEOMOp::OpProjOnCyl, "PROJ_ON_CYL" ); createGeomAction( GEOMOp::OpMultiTranslate, "MUL_TRANSLATION" ); createGeomAction( GEOMOp::OpMultiRotate, "MUL_ROTATION" ); createGeomAction( GEOMOp::OpExtension, "EXTENSION" ); @@ -1211,6 +1213,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createMenu( GEOMOp::OpOffset, transId, -1 ); createMenu( GEOMOp::OpProjection, transId, -1 ); createMenu( GEOMOp::OpExtension, transId, -1 ); + createMenu( GEOMOp::OpProjOnCyl, transId, -1 ); createMenu( separator(), transId, -1 ); createMenu( GEOMOp::OpMultiTranslate, transId, -1 ); createMenu( GEOMOp::OpMultiRotate, transId, -1 ); @@ -1386,6 +1389,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createTool( GEOMOp::OpOffset, transTbId ); createTool( GEOMOp::OpProjection, transTbId ); createTool( GEOMOp::OpExtension, transTbId ); + createTool( GEOMOp::OpProjOnCyl, transTbId ); createTool( separator(), transTbId ); createTool( GEOMOp::OpMultiTranslate, transTbId ); createTool( GEOMOp::OpMultiRotate, transTbId ); diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h index 2acdd53f4..915f5d1f1 100644 --- a/src/GEOMGUI/GeometryGUI_Operations.h +++ b/src/GEOMGUI/GeometryGUI_Operations.h @@ -148,6 +148,7 @@ namespace GEOMOp { OpReimport = 3608, // POPUP MENU - RELOAD IMPORTED OpProjection = 3609, // MENU OPERATIONS - TRANSFORMATION - PROJECTION OpExtension = 3610, // MENU OPERATIONS - TRANSFORMATION - EXTENSION + OpProjOnCyl = 3611, // MENU OPERATIONS - TRANSFORMATION - PROJECTION ON CYLINDER // OperationGUI ----------------//-------------------------------- OpPartition = 3700, // MENU OPERATION - PARTITION OpArchimede = 3701, // MENU OPERATION - ARCHIMEDE diff --git a/src/GEOMImpl/CMakeLists.txt b/src/GEOMImpl/CMakeLists.txt index 5cc90b4ed..5c59b2e72 100755 --- a/src/GEOMImpl/CMakeLists.txt +++ b/src/GEOMImpl/CMakeLists.txt @@ -97,6 +97,7 @@ SET(GEOMImpl_HEADERS GEOMImpl_ITranslate.hxx GEOMImpl_IMirror.hxx GEOMImpl_IProjection.hxx + GEOMImpl_IProjOnCyl.hxx GEOMImpl_IOffset.hxx GEOMImpl_IScale.hxx GEOMImpl_IRotate.hxx diff --git a/src/GEOMImpl/GEOMImpl_IProjOnCyl.hxx b/src/GEOMImpl/GEOMImpl_IProjOnCyl.hxx new file mode 100644 index 000000000..9fc6024d1 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_IProjOnCyl.hxx @@ -0,0 +1,61 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// + +//NOTE: This is an interface to a function for the Projection on cylinder creation. + +#include "GEOM_Function.hxx" + +#define PROJECTION_ARG_SHAPE 1 +#define PROJECTION_ARG_RADIUS 2 +#define PROJECTION_ARG_START_ANGLE 3 +#define PROJECTION_ARG_ANGLE_LENGTH 4 + +class GEOMImpl_IProjOnCyl +{ + +public: + + GEOMImpl_IProjOnCyl(Handle(GEOM_Function) theFunction): _func(theFunction) {} + + void SetShape (const Handle(GEOM_Function) &theShape) + { _func->SetReference(PROJECTION_ARG_SHAPE, theShape); } + void SetRadius (const Standard_Real theRadius) + { _func->SetReal(PROJECTION_ARG_RADIUS, theRadius); } + void SetStartAngle (const Standard_Real theStartAngle) + { _func->SetReal(PROJECTION_ARG_START_ANGLE, theStartAngle); } + void SetAngleLength (const Standard_Real theAngleLength) + { _func->SetReal(PROJECTION_ARG_ANGLE_LENGTH, theAngleLength); } + + Handle(GEOM_Function) GetShape() + { return _func->GetReference(PROJECTION_ARG_SHAPE); } + Standard_Real GetRadius() + { return _func->GetReal(PROJECTION_ARG_RADIUS ); } + Standard_Real GetStartAngle() + { return _func->GetReal(PROJECTION_ARG_START_ANGLE ); } + Standard_Real GetAngleLength() + { return _func->GetReal(PROJECTION_ARG_ANGLE_LENGTH ); } + + private: + + Handle(GEOM_Function) _func; + +}; diff --git a/src/GEOMImpl/GEOMImpl_ITransformOperations.cxx b/src/GEOMImpl/GEOMImpl_ITransformOperations.cxx index 766531fdb..5d89b0c0a 100644 --- a/src/GEOMImpl/GEOMImpl_ITransformOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_ITransformOperations.cxx @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -2267,3 +2268,78 @@ Handle(GEOM_Object) GEOMImpl_ITransformOperations::TransformLikeOtherCopy SetErrorCode(OK); return aCopy; } + +//============================================================================= +/*! + * MakeProjectionOnCylinder + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_ITransformOperations::MakeProjectionOnCylinder + (const Handle(GEOM_Object) &theObject, + const Standard_Real theRadius, + const Standard_Real theStartAngle, + const Standard_Real theAngleLength) +{ + SetErrorCode(KO); + + if (theObject.IsNull()) { + return NULL; + } + + Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction(); + + if (aLastFunction.IsNull()) { + //There is no function which creates an object to be projected + return NULL; + } + + //Add a new Projection object + Handle(GEOM_Object) aResult = + GetEngine()->AddObject(GetDocID(), GEOM_PROJECTION); + + //Add a Projection function + Handle(GEOM_Function) aFunction = aResult->AddFunction + (GEOMImpl_ProjectionDriver::GetID(), PROJECTION_ON_CYLINDER); + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ProjectionDriver::GetID()) { + return aResult; + } + + GEOMImpl_IProjOnCyl aProj (aFunction); + + aProj.SetShape(aLastFunction); + aProj.SetRadius(theRadius); + aProj.SetStartAngle(theStartAngle); + aProj.SetAngleLength(theAngleLength); + + //Compute the Projection + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Projection driver failed"); + return aResult; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return aResult; + } + + //Make a Python command + GEOM::TPythonDump pd(aFunction); + + pd << aResult << " = geompy.MakeProjectionOnCylinder(" + << theObject << ", " << theRadius << ", " << theStartAngle; + + if (theAngleLength >= 0.) { + pd << ", " << theAngleLength; + } + + pd << ")"; + + SetErrorCode(OK); + + return aResult; +} diff --git a/src/GEOMImpl/GEOMImpl_ITransformOperations.hxx b/src/GEOMImpl/GEOMImpl_ITransformOperations.hxx index 2c44b3854..155dbfdd9 100644 --- a/src/GEOMImpl/GEOMImpl_ITransformOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_ITransformOperations.hxx @@ -191,6 +191,12 @@ class GEOMImpl_ITransformOperations : public GEOM_IOperations Standard_EXPORT Handle(GEOM_Object) TransformLikeOtherCopy (Handle(GEOM_Object) theObject, Handle(GEOM_Object) theSample); + Standard_EXPORT Handle(GEOM_Object) MakeProjectionOnCylinder + (const Handle(GEOM_Object) &theObject, + const Standard_Real theRadius, + const Standard_Real theStartAngle, + const Standard_Real theAngleLength); + }; #endif diff --git a/src/GEOMImpl/GEOMImpl_ProjectionDriver.cxx b/src/GEOMImpl/GEOMImpl_ProjectionDriver.cxx index 064dbb91b..d226969c8 100644 --- a/src/GEOMImpl/GEOMImpl_ProjectionDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_ProjectionDriver.cxx @@ -26,16 +26,26 @@ #include #include +#include #include #include +#include +#include +#include #include +#include #include +#include +#include #include +#include #include #include +#include #include #include +#include #include #include @@ -44,11 +54,14 @@ #include #include #include -#include +#include +#include #include #include +#include #include +#include #include #include @@ -400,6 +413,42 @@ Standard_Integer GEOMImpl_ProjectionDriver::Execute(TFunction_Logbook& log) cons if (!hasValidSolution) { Standard_ConstructionError::Raise("Projection aborted : no projection"); } + } else if (aType == PROJECTION_ON_CYLINDER) { + GEOMImpl_IProjOnCyl aProj (aFunction); + Handle(GEOM_Function) aShapeFunction = aProj.GetShape(); + + if (aShapeFunction.IsNull()) { + return 0; + } + + TopoDS_Shape aShape = aShapeFunction->GetValue(); + + if (aShape.IsNull()) { + return 0; + } + + // Get the face. + const TopAbs_ShapeEnum aType = aShape.ShapeType(); + const Standard_Real aRadius = aProj.GetRadius(); + const Standard_Real aStartAngle = aProj.GetStartAngle(); + const Standard_Real aLengthAngle = aProj.GetAngleLength(); + + if (aType != TopAbs_WIRE && aType != TopAbs_FACE) { + return 0; + } + + if (aRadius <= Precision::Confusion()) { + return 0; + } + + TopoDS_Shape aProjShape = + projectOnCylinder(aShape, aRadius, aStartAngle, aLengthAngle); + + if (aProjShape.IsNull()) { + return 0; + } + + aFunction->SetValue(aProjShape); } return 1; @@ -438,6 +487,21 @@ GetCreationInformation(std::string& theOperationName, AddParam(theParams, "Point", aProj.GetPoint()); AddParam(theParams, "Shape", aProj.GetShape()); + break; + } + case PROJECTION_ON_CYLINDER: + { + GEOMImpl_IProjOnCyl aProj (function); + const Standard_Real aLengthAngle = aProj.GetAngleLength(); + + AddParam(theParams, "Shape", aProj.GetShape()); + AddParam(theParams, "Radius", aProj.GetRadius()); + AddParam(theParams, "Start angle", aProj.GetStartAngle()); + + if (aLengthAngle >= 0.) { + AddParam(theParams, "Length angle", aLengthAngle); + } + break; } default: @@ -447,5 +511,242 @@ GetCreationInformation(std::string& theOperationName, return true; } +//================================================================================ +/*! + * \brief Performs projection of a planar wire or a face on a cylinder. + */ +//================================================================================ + +TopoDS_Shape GEOMImpl_ProjectionDriver::projectOnCylinder + (const TopoDS_Shape &theShape, + const Standard_Real theRadius, + const Standard_Real theStartAngle, + const Standard_Real theAngleLength) const +{ + TopoDS_Shape aResult; + + // Get the face. + const TopAbs_ShapeEnum aType = theShape.ShapeType(); + TopoDS_Face aFace; + + if (aType == TopAbs_WIRE) { + // Try to create a planar face. + TopoDS_Wire aWire = TopoDS::Wire(theShape); + BRepBuilderAPI_MakeFace aMkFace(aWire, Standard_True); + + if (aMkFace.IsDone()) { + aFace = aMkFace.Face(); + } else { + // Check if the wire is a straight line. + TopExp_Explorer anEExp(aWire, TopAbs_EDGE); + TopoDS_Edge anEdge; + + for (; anEExp.More(); anEExp.Next()) { + anEdge = TopoDS::Edge(anEExp.Current()); + + if (!BRep_Tool::Degenerated(anEdge)) { + break; + } + } + + if (anEExp.More()) { + // Not degenerated edge found. Try to create a plane. + Standard_Real aPar[2]; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aPar[0], aPar[1]); + gp_Pnt aP0 = aCurve->Value(aPar[0]); + gp_Pnt aP1 = aCurve->Value(0.5*(aPar[1] + aPar[0])); + gp_Vec aX(aP1.XYZ().Subtracted(aP0.XYZ())); + Standard_Real aTolConf = Precision::Confusion(); + + if (aX.Magnitude() > aTolConf) { + aX.Normalize(); + + // Get the plane normal ortogonal to Z axis. + gp_Vec aZ(0., 0., 1.); + gp_Vec aN = aX.Crossed(aZ); + + if (aN.Magnitude() <= aTolConf) { + // aX is parallel to aZ. Get the plane normal ortogonal to Y axis. + gp_Vec aY(0., 1., 0.); + + aN = aX.Crossed(aY); + } + + if (aN.Magnitude() > aTolConf) { + gp_Ax3 anAxis(aP0, gp_Dir(aN), gp_Dir(aX)); + Handle(Geom_Plane) aPlane = new Geom_Plane(anAxis); + BRepBuilderAPI_MakeFace aMkFace(aPlane, aWire); + + if (aMkFace.IsDone()) { + aFace = aMkFace.Face(); + } + } + } + } + } + } else if (aType == TopAbs_FACE) { + aFace = TopoDS::Face(theShape); + } + + if (aFace.IsNull()) { + return aResult; + } + + // Compute 2d translation transformation. + TopoDS_Wire anOuterWire = BRepTools::OuterWire(aFace); + Standard_Real aU[2]; + Standard_Real aV[2]; + BRepTools_WireExplorer aOWExp(anOuterWire, aFace); + + if (!aOWExp.More()) { + // NEVERREACHED + return aResult; + } + + // Compute anisotropic transformation from a face's 2d space + // to cylinder's 2d space. + BRepTools::UVBounds(aFace, anOuterWire, aU[0], aU[1], aV[0], aV[1]); + + TopoDS_Vertex aFirstVertex = aOWExp.CurrentVertex(); + TopoDS_Edge aFirstEdge = aOWExp.Current(); + gp_Pnt aPnt = BRep_Tool::Pnt(aFirstVertex); + BRepAdaptor_Curve2d anAdaptorCurve(aFirstEdge, aFace); + Standard_Real aParam = + BRep_Tool::Parameter(aFirstVertex, aFirstEdge, aFace); + gp_Pnt2d aPntUV = anAdaptorCurve.Value(aParam); + + GEOMUtils::Trsf2d aTrsf2d + (1./theRadius, 0., theStartAngle - aU[0]/theRadius, + 0., 1., aPnt.Z() - 0.5*(aV[1] - aV[0]) - aPntUV.Y()); + + // Compute scaling trsf. + const Standard_Boolean isToScale = theAngleLength >= Precision::Angular(); + gp_Trsf2d aScaleTrsf; + + if (isToScale) { + // Perform 2d scaling. + gp_Pnt2d aMidPnt(0.5*(aU[1] + aU[0]), 0.5*(aV[1] + aV[0])); + const Standard_Real aScaleFactor = theAngleLength*theRadius/(aU[1] - aU[0]); + + aTrsf2d.TransformD0(aMidPnt); + + aScaleTrsf.SetScale(aMidPnt, aScaleFactor); + } + + // Get 2d presentation of a face. + Handle(Geom_Surface) aCylinder = + new Geom_CylindricalSurface(gp_Ax3(), theRadius); + GeomAdaptor_Surface aGACyl(aCylinder); + TopExp_Explorer anExp(aFace, TopAbs_WIRE); + Standard_Real aPar[2]; + TopTools_ListOfShape aWires; + Standard_Real aUResol = aGACyl.UResolution(Precision::Confusion()); + Standard_Real aVResol = aGACyl.VResolution(Precision::Confusion()); + + for (; anExp.More(); anExp.Next()) { + TopoDS_Wire aWire = TopoDS::Wire(anExp.Current()); + BRepTools_WireExplorer aWExp(aWire, aFace); + BRepBuilderAPI_MakeWire aMkWire; + + for (; aWExp.More(); aWExp.Next()) { + TopoDS_Edge anEdge = aWExp.Current(); + Handle(Geom2d_Curve) aCurve = + BRep_Tool::CurveOnSurface(anEdge, aFace, aPar[0], aPar[1]); + + if (aCurve.IsNull()) { + continue; + } + + // Transform the curve to cylinder's parametric space. + GEOMUtils::Handle(HTrsfCurve2d) aTrsfCurve = + new GEOMUtils::HTrsfCurve2d(aCurve, aPar[0], aPar[1], aTrsf2d); + Approx_Curve2d aConv (aTrsfCurve, aPar[0], aPar[1], + aUResol, aVResol, GeomAbs_C1, + 9, 1000); + + if (!aConv.IsDone() && !aConv.HasResult()) { + return aResult; + } + + Handle(Geom2d_Curve) aCylCurve = aConv.Curve(); + + if (isToScale) { + aCylCurve->Transform(aScaleTrsf); + } + + // Create edge and add it to the wire. + BRepBuilderAPI_MakeEdge aMkEdge(aCylCurve, aCylinder); + + if (!aMkEdge.IsDone()) { + return aResult; + } + + aMkWire.Add(aMkEdge.Edge()); + + if (!aMkWire.IsDone()) { + return aResult; + } + } + + if (aWire.IsSame(anOuterWire)) { + // Make the outer wire first. + aWires.Prepend(aMkWire.Wire()); + } else { + aWires.Append(aMkWire.Wire()); + } + } + + // Create a face. + if (aWires.IsEmpty()) { + return aResult; + } + + TopTools_ListIteratorOfListOfShape aWIter(aWires); + TopoDS_Wire aWire = TopoDS::Wire(aWIter.Value()); + BRepBuilderAPI_MakeFace aMkFace(aCylinder, aWire); + + if (!aMkFace.IsDone()) { + return aResult; + } + + for (aWIter.Next(); aWIter.More(); aWIter.Next()) { + aWire = TopoDS::Wire(aWIter.Value()); + aMkFace.Add(aWire); + + if (!aMkFace.IsDone()) { + return aResult; + } + } + + // Build 3D curves. + TopoDS_Face aCylFace = aMkFace.Face(); + TopoDS_Shape aResShape; + + BRepLib::BuildCurves3d(aCylFace); + + // Check shape. + if (aType == TopAbs_WIRE) { + TopExp_Explorer aResExp(aCylFace, TopAbs_WIRE); + + if (aResExp.More()) { + aResShape = aResExp.Current(); + } + } else { + aResShape = aCylFace; + } + + if (aResShape.IsNull() == Standard_False) { + if (!GEOMUtils::CheckShape(aResShape, true)) { + if (!GEOMUtils::FixShapeTolerance(aResShape)) { + return aResult; + } + } + + aResult = aResShape; + } + + return aResult; +} + IMPLEMENT_STANDARD_HANDLE (GEOMImpl_ProjectionDriver,GEOM_BaseDriver); IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_ProjectionDriver,GEOM_BaseDriver); diff --git a/src/GEOMImpl/GEOMImpl_ProjectionDriver.hxx b/src/GEOMImpl/GEOMImpl_ProjectionDriver.hxx index 5766c2392..ee703af55 100644 --- a/src/GEOMImpl/GEOMImpl_ProjectionDriver.hxx +++ b/src/GEOMImpl/GEOMImpl_ProjectionDriver.hxx @@ -58,6 +58,7 @@ #endif class TColStd_SequenceOfExtendedString; +class TopoDS_Shape; #include "GEOM_BaseDriver.hxx" @@ -81,6 +82,15 @@ Standard_EXPORT ~GEOMImpl_ProjectionDriver() {}; bool GetCreationInformation(std::string& theOperationName, std::vector& params); +private: + + TopoDS_Shape projectOnCylinder(const TopoDS_Shape &theShape, + const Standard_Real theRadius, + const Standard_Real theStartAngle, + const Standard_Real theAngleLength) const; + +public: + DEFINE_STANDARD_RTTI( GEOMImpl_ProjectionDriver ) }; diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx index f4e151969..393b4303c 100644 --- a/src/GEOMImpl/GEOMImpl_Types.hxx +++ b/src/GEOMImpl/GEOMImpl_Types.hxx @@ -185,8 +185,9 @@ #define OFFSET_THICKENING 3 #define OFFSET_THICKENING_COPY 4 -#define PROJECTION_COPY 1 -#define PROJECTION_ON_WIRE 2 +#define PROJECTION_COPY 1 +#define PROJECTION_ON_WIRE 2 +#define PROJECTION_ON_CYLINDER 3 #define SCALE_SHAPE 1 #define SCALE_SHAPE_COPY 2 diff --git a/src/GEOMUtils/CMakeLists.txt b/src/GEOMUtils/CMakeLists.txt index 4368a6342..039990ab7 100755 --- a/src/GEOMUtils/CMakeLists.txt +++ b/src/GEOMUtils/CMakeLists.txt @@ -52,6 +52,9 @@ SET(_link_LIBRARIES SET(GEOMUtils_HEADERS GEOMUtils.hxx GEOMUtils_Hatcher.hxx + GEOMUtils_HTrsfCurve2d.hxx + GEOMUtils_Trsf2d.hxx + GEOMUtils_TrsfCurve2d.hxx GEOMUtils_XmlHandler.hxx ) # --- sources --- @@ -59,6 +62,9 @@ SET(GEOMUtils_HEADERS SET(GEOMUtils_SOURCES GEOMUtils.cxx GEOMUtils_Hatcher.cxx + GEOMUtils_HTrsfCurve2d.cxx + GEOMUtils_Trsf2d.cxx + GEOMUtils_TrsfCurve2d.cxx GEOMUtils_XmlHandler.cxx ) diff --git a/src/GEOMUtils/GEOMUtils_HTrsfCurve2d.cxx b/src/GEOMUtils/GEOMUtils_HTrsfCurve2d.cxx new file mode 100644 index 000000000..976d29690 --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_HTrsfCurve2d.cxx @@ -0,0 +1,51 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// + + +#include + +namespace GEOMUtils { + IMPLEMENT_STANDARD_HANDLE (HTrsfCurve2d, Adaptor2d_HCurve2d); + IMPLEMENT_STANDARD_RTTIEXT(HTrsfCurve2d, Adaptor2d_HCurve2d); +} + +//======================================================================= +//function : TrsfCurve2d +//purpose : +//======================================================================= +GEOMUtils::HTrsfCurve2d::HTrsfCurve2d(const Handle(Geom2d_Curve) &theCurve, + const Trsf2d &theTrsf) +: myCurve (theCurve, theTrsf) +{ +} + +//======================================================================= +//function : TrsfCurve2d +//purpose : +//======================================================================= +GEOMUtils::HTrsfCurve2d::HTrsfCurve2d(const Handle(Geom2d_Curve) &theCurve, + const Standard_Real theUFirst, + const Standard_Real theULast, + const Trsf2d &theTrsf) +: myCurve (theCurve, theUFirst, theULast, theTrsf) +{ +} diff --git a/src/GEOMUtils/GEOMUtils_HTrsfCurve2d.hxx b/src/GEOMUtils/GEOMUtils_HTrsfCurve2d.hxx new file mode 100644 index 000000000..d37b7f293 --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_HTrsfCurve2d.hxx @@ -0,0 +1,84 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// + +#ifndef _GEOMUtils_HTrsfCurve2d_HXX_ +#define _GEOMUtils_HTrsfCurve2d_HXX_ + + +#include + +#include + + +namespace GEOMUtils +{ + + class HTrsfCurve2d; + + DEFINE_STANDARD_HANDLE(HTrsfCurve2d, Adaptor2d_HCurve2d); + + /*! + * This class represents an adaptor curve that represents an original curve + * transformed by an anisotropic transformation. This is a class manipulated + * by handle. + */ + class HTrsfCurve2d : public Adaptor2d_HCurve2d + { + + public: + + /** + * Constructor. Initializes the object with the transformation parameters. + * Input parameters are not checked for validity. It is under responsibility + * of the caller. + */ + Standard_EXPORT HTrsfCurve2d(const Handle(Geom2d_Curve) &theCurve, + const Trsf2d &theTrsf); + + /** + * Constructor. Initializes the object with the curve, first and last + * parameters and transformation. Input parameters are not checked + * for validity. It is under responsibility of the caller. + */ + Standard_EXPORT HTrsfCurve2d(const Handle(Geom2d_Curve) &theCurve, + const Standard_Real theUFirst, + const Standard_Real theULast, + const Trsf2d &theTrsf); + + /** + * Redefined method from the base class. + */ + const Adaptor2d_Curve2d &Curve2d() const + { return myCurve; } + + private: + + TrsfCurve2d myCurve; + + public: + + DEFINE_STANDARD_RTTI(HTrsfCurve2d); + + }; +} + +#endif diff --git a/src/GEOMUtils/GEOMUtils_Trsf2d.cxx b/src/GEOMUtils/GEOMUtils_Trsf2d.cxx new file mode 100644 index 000000000..4938d4979 --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_Trsf2d.cxx @@ -0,0 +1,110 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// + + +#include + + +//======================================================================= +//function : Trsf2d +//purpose : +//======================================================================= +GEOMUtils::Trsf2d::Trsf2d(const Standard_Real a11, + const Standard_Real a12, + const Standard_Real a13, + const Standard_Real a21, + const Standard_Real a22, + const Standard_Real a23) +: myA11(a11), + myA12(a12), + myA13(a13), + myA21(a21), + myA22(a22), + myA23(a23) +{ +} + +//======================================================================= +//function : TransformD0 +//purpose : +//======================================================================= +void GEOMUtils::Trsf2d::TransformD0(gp_Pnt2d &thePnt) const +{ + const Standard_Real aX = myA11*thePnt.X() + myA12*thePnt.Y() + myA13; + const Standard_Real aY = myA21*thePnt.X() + myA22*thePnt.Y() + myA23; + + thePnt.SetCoord(aX, aY); +} + +//======================================================================= +//function : TransformD1 +//purpose : +//======================================================================= +void GEOMUtils::Trsf2d::TransformD1(gp_Pnt2d &thePnt, + gp_Vec2d &theVec1) const +{ + TransformVector(thePnt, theVec1); + TransformD0(thePnt); +} + +//======================================================================= +//function : TransformD2 +//purpose : +//======================================================================= +void GEOMUtils::Trsf2d::TransformD2(gp_Pnt2d &thePnt, + gp_Vec2d &theVec1, + gp_Vec2d &theVec2) const +{ + TransformVector(thePnt, theVec1); + TransformVector(thePnt, theVec2); + TransformD0(thePnt); +} + +//======================================================================= +//function : TransformD3 +//purpose : +//======================================================================= +void GEOMUtils::Trsf2d::TransformD3(gp_Pnt2d &thePnt, + gp_Vec2d &theVec1, + gp_Vec2d &theVec2, + gp_Vec2d &theVec3) const +{ + TransformVector(thePnt, theVec1); + TransformVector(thePnt, theVec2); + TransformVector(thePnt, theVec3); + TransformD0(thePnt); +} + +//======================================================================= +//function : TransformVector +//purpose : +//======================================================================= +void GEOMUtils::Trsf2d::TransformVector(const gp_Pnt2d &thePnt, + gp_Vec2d &theVec) const +{ + gp_Pnt2d aP0(thePnt.XY()); + gp_Pnt2d aP1(thePnt.XY().Added(theVec.XY())); + + TransformD0(aP0); + TransformD0(aP1); + theVec.SetXY(aP1.XY().Subtracted(aP0.XY())); +} diff --git a/src/GEOMUtils/GEOMUtils_Trsf2d.hxx b/src/GEOMUtils/GEOMUtils_Trsf2d.hxx new file mode 100644 index 000000000..c287f90d8 --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_Trsf2d.hxx @@ -0,0 +1,134 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// + +#ifndef _GEOMUtils_Trsf2d_HXX_ +#define _GEOMUtils_Trsf2d_HXX_ + + +#include +#include +#include +#include +#include + + +/*! + * This class represents a non-persistent transformation in 2D space. + * The transformations can be represented as follow : + * + * V1 V2 T XY XY + * | a11 a12 a13 | | x | | x'| + * | a21 a22 a23 | | y | | y'| + * | 0 0 1 | | 1 | | 1 | + + * where {V1, V2} defines the vectorial part of the transformation + * and T defines the translation part of the transformation. + * This transformation can change the nature of the objects if it is + * anisotropic. + */ +namespace GEOMUtils +{ + class Trsf2d + { + + public: + + /** + * Constructor. Initializes the object with the transformation parameters. + * Input parameters are not checked for validity. It is under responsibility + * of the caller. + */ + Standard_EXPORT Trsf2d(const Standard_Real a11, + const Standard_Real a12, + const Standard_Real a13, + const Standard_Real a21, + const Standard_Real a22, + const Standard_Real a23); + + /** + * Transform the point. The passed parameter is modified to have + * a transformed value. + * + * \param thePnt the point. + */ + Standard_EXPORT void TransformD0(gp_Pnt2d &thePnt)const; + + /** + * Transform the point and the first derivative vector. The passed + * parameters are modified to have a transformed value. + * + * \param thePnt the point. + * \param theVec1 the first derivative vector. + */ + Standard_EXPORT void TransformD1(gp_Pnt2d &thePnt, + gp_Vec2d &theVec1) const; + + /** + * Transform the point, the first and second derivative vectors. The passed + * parameters are modified to have a transformed value. + * + * \param thePnt the point. + * \param theVec1 the first derivative vector. + * \param theVec2 the second derivative vector. + */ + Standard_EXPORT void TransformD2(gp_Pnt2d &thePnt, + gp_Vec2d &theVec1, + gp_Vec2d &theVec2) const; + + /** + * Transform the point, the first, second and third derivative vectors. + * The passed parameters are modified to have a transformed value. + * + * \param thePnt the point. + * \param theVec1 the first derivative vector. + * \param theVec2 the second derivative vector. + * \param theVec2 the third derivative vector. + */ + Standard_EXPORT void TransformD3(gp_Pnt2d &thePnt, + gp_Vec2d &theVec1, + gp_Vec2d &theVec2, + gp_Vec2d &theVec3) const; + + private: + + /** + * Transform the vector. + * + * \param thePnt the point. + * \param theVec the vector. + */ + void TransformVector(const gp_Pnt2d &thePnt, + gp_Vec2d &theVec) const; + + private: + + Standard_Real myA11; + Standard_Real myA12; + Standard_Real myA13; + Standard_Real myA21; + Standard_Real myA22; + Standard_Real myA23; + + }; +} + +#endif diff --git a/src/GEOMUtils/GEOMUtils_TrsfCurve2d.cxx b/src/GEOMUtils/GEOMUtils_TrsfCurve2d.cxx new file mode 100644 index 000000000..fe0707eb9 --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_TrsfCurve2d.cxx @@ -0,0 +1,382 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// + + +#include +#include + +//======================================================================= +//function : TrsfCurve2d +//purpose : +//======================================================================= +GEOMUtils::TrsfCurve2d::TrsfCurve2d(const Handle(Geom2d_Curve) &theCurve, + const Trsf2d &theTrsf) +: myCurve (theCurve), + myTrsf (theTrsf) +{ +} + +//======================================================================= +//function : TrsfCurve2d +//purpose : +//======================================================================= +GEOMUtils::TrsfCurve2d::TrsfCurve2d(const Handle(Geom2d_Curve) &theCurve, + const Standard_Real theUFirst, + const Standard_Real theULast, + const Trsf2d &theTrsf) +: myCurve (theCurve, theUFirst, theULast), + myTrsf (theTrsf) +{ +} + +//======================================================================= +//function : FirstParameter +//purpose : +//======================================================================= +Standard_Real GEOMUtils::TrsfCurve2d::FirstParameter() const +{ + return myCurve.FirstParameter(); +} + +//======================================================================= +//function : LastParameter +//purpose : +//======================================================================= +Standard_Real GEOMUtils::TrsfCurve2d::LastParameter() const +{ + return myCurve.LastParameter(); +} + +//======================================================================= +//function : Curve +//purpose : +//======================================================================= +const Handle(Geom2d_Curve) &GEOMUtils::TrsfCurve2d::Curve() const +{ + return myCurve.Curve(); +} + +//======================================================================= +//function : GetType +//purpose : +//======================================================================= +GeomAbs_CurveType GEOMUtils::TrsfCurve2d::GetType() const +{ + return GeomAbs_OtherCurve; +} + +//======================================================================= +//function : Load +//purpose : +//======================================================================= +void GEOMUtils::TrsfCurve2d::Load(const Handle(Geom2d_Curve) &C) +{ + myCurve.Load(C); +} + +//======================================================================= +//function : Load +//purpose : +//======================================================================= +void GEOMUtils::TrsfCurve2d::Load(const Handle(Geom2d_Curve) &C, + const Standard_Real UFirst, + const Standard_Real ULast) +{ + myCurve.Load(C, UFirst, ULast); +} + +//======================================================================= +//function : Continuity +//purpose : +//======================================================================= +GeomAbs_Shape GEOMUtils::TrsfCurve2d::Continuity() const +{ + return myCurve.Continuity(); +} + +//======================================================================= +//function : NbIntervals +//purpose : +//======================================================================= +Standard_Integer GEOMUtils::TrsfCurve2d::NbIntervals + (const GeomAbs_Shape S) const +{ + return myCurve.NbIntervals(S); +} + +//======================================================================= +//function : Intervals +//purpose : +//======================================================================= +void GEOMUtils::TrsfCurve2d::Intervals(TColStd_Array1OfReal &T, + const GeomAbs_Shape S) const +{ + myCurve.Intervals(T, S); +} + +//======================================================================= +//function : Trim +//purpose : +//======================================================================= +Handle(Adaptor2d_HCurve2d) GEOMUtils::TrsfCurve2d::Trim + (const Standard_Real First, const Standard_Real Last, + const Standard_Real /*Tol*/) const +{ + Handle(Geom2d_Curve) aCurve = myCurve.Curve(); + GEOMUtils::Handle(HTrsfCurve2d) aAHCurve = + new GEOMUtils::HTrsfCurve2d(aCurve, First, Last, myTrsf); + + return aAHCurve; +} + +//======================================================================= +//function : IsClosed +//purpose : +//======================================================================= +Standard_Boolean GEOMUtils::TrsfCurve2d::IsClosed() const +{ + return myCurve.IsClosed(); +} + +//======================================================================= +//function : IsPeriodic +//purpose : +//======================================================================= +Standard_Boolean GEOMUtils::TrsfCurve2d::IsPeriodic() const +{ + return myCurve.IsPeriodic(); +} + +//======================================================================= +//function : Period +//purpose : +//======================================================================= +Standard_Real GEOMUtils::TrsfCurve2d::Period() const +{ + return myCurve.Period(); +} + +//======================================================================= +//function : Value +//purpose : +//======================================================================= +gp_Pnt2d GEOMUtils::TrsfCurve2d::Value(const Standard_Real U) const +{ + gp_Pnt2d aPnt = myCurve.Value(U); + + myTrsf.TransformD0(aPnt); + + return aPnt; +} + +//======================================================================= +//function : D0 +//purpose : +//======================================================================= +void GEOMUtils::TrsfCurve2d::D0(const Standard_Real U, gp_Pnt2d &P) const +{ + myCurve.D0(U, P); + myTrsf.TransformD0(P); +} + +//======================================================================= +//function : D1 +//purpose : +//======================================================================= +void GEOMUtils::TrsfCurve2d::D1(const Standard_Real U, + gp_Pnt2d &P, gp_Vec2d &V) const +{ + myCurve.D1(U, P, V); + myTrsf.TransformD1(P, V); +} + +//======================================================================= +//function : D2 +//purpose : +//======================================================================= +void GEOMUtils::TrsfCurve2d::D2(const Standard_Real U, gp_Pnt2d &P, + gp_Vec2d &V1, gp_Vec2d &V2) const +{ + myCurve.D2(U, P, V1, V2); + myTrsf.TransformD2(P, V1, V2); +} + +//======================================================================= +//function : D3 +//purpose : +//======================================================================= +void GEOMUtils::TrsfCurve2d::D3(const Standard_Real U, gp_Pnt2d &P, + gp_Vec2d &V1, gp_Vec2d &V2, gp_Vec2d &V3) const +{ + myCurve.D3(U, P, V1, V2, V3); + myTrsf.TransformD3(P, V1, V2, V3); +} + +//======================================================================= +//function : DN +//purpose : +//======================================================================= +gp_Vec2d GEOMUtils::TrsfCurve2d::DN(const Standard_Real U, + const Standard_Integer N) const +{ + gp_Pnt2d aPnt = myCurve.Value(U); + gp_Vec2d aVec = myCurve.DN(U, N); + + myTrsf.TransformD1(aPnt, aVec); +} + +//======================================================================= +//function : Resolution +//purpose : +//======================================================================= +Standard_Real GEOMUtils::TrsfCurve2d::Resolution(const Standard_Real Ruv) const +{ + return Precision::Parametric(Ruv); +} + +//======================================================================= +//function : Line +//purpose : +//======================================================================= +gp_Lin2d GEOMUtils::TrsfCurve2d::Line() const +{ + Standard_NoSuchObject::Raise(); + + return gp_Lin2d(); +} + +//======================================================================= +//function : Circle +//purpose : +//======================================================================= +gp_Circ2d GEOMUtils::TrsfCurve2d::Circle() const +{ + Standard_NoSuchObject::Raise(); + + return gp_Circ2d(); +} + +//======================================================================= +//function : Ellipse +//purpose : +//======================================================================= +gp_Elips2d GEOMUtils::TrsfCurve2d::Ellipse() const +{ + Standard_NoSuchObject::Raise(); + + return gp_Elips2d(); +} + +//======================================================================= +//function : Hyperbola +//purpose : +//======================================================================= +gp_Hypr2d GEOMUtils::TrsfCurve2d::Hyperbola() const +{ + Standard_NoSuchObject::Raise(); + + return gp_Hypr2d(); +} + +//======================================================================= +//function : Parabola +//purpose : +//======================================================================= +gp_Parab2d GEOMUtils::TrsfCurve2d::Parabola() const +{ + Standard_NoSuchObject::Raise(); + + return gp_Parab2d(); +} + +//======================================================================= +//function : Degree +//purpose : +//======================================================================= +Standard_Integer GEOMUtils::TrsfCurve2d::Degree() const +{ + Standard_NoSuchObject::Raise(); + + return 0; +} + +//======================================================================= +//function : IsRational +//purpose : +//======================================================================= +Standard_Boolean GEOMUtils::TrsfCurve2d::IsRational() const +{ + return Standard_False; +} + +//======================================================================= +//function : NbPoles +//purpose : +//======================================================================= +Standard_Integer GEOMUtils::TrsfCurve2d::NbPoles() const +{ + Standard_NoSuchObject::Raise(); + + return 0; +} + +//======================================================================= +//function : NbKnots +//purpose : +//======================================================================= +Standard_Integer GEOMUtils::TrsfCurve2d::NbKnots() const +{ + Standard_NoSuchObject::Raise(); + + return 0; +} + +//======================================================================= +//function : Bezier +//purpose : +//======================================================================= +Handle(Geom2d_BezierCurve) GEOMUtils::TrsfCurve2d::Bezier() const +{ + Standard_NoSuchObject::Raise(); + + return NULL; +} + +//======================================================================= +//function : BSpline +//purpose : +//======================================================================= +Handle(Geom2d_BSplineCurve) GEOMUtils::TrsfCurve2d::BSpline() const +{ + Standard_NoSuchObject::Raise(); + + return NULL; +} + +//======================================================================= +//function : NbSamples +//purpose : +//======================================================================= +Standard_Integer GEOMUtils::TrsfCurve2d::NbSamples() const +{ + return myCurve.NbSamples(); +} diff --git a/src/GEOMUtils/GEOMUtils_TrsfCurve2d.hxx b/src/GEOMUtils/GEOMUtils_TrsfCurve2d.hxx new file mode 100644 index 000000000..b3bd19433 --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_TrsfCurve2d.hxx @@ -0,0 +1,242 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// + +#ifndef _GEOMUtils_TrsfCurve2d_HXX_ +#define _GEOMUtils_TrsfCurve2d_HXX_ + + +#include + +#include +#include +#include +#include +#include + + +namespace GEOMUtils +{ + /*! + * This class represents an adaptor curve that represents an original curve + * transformed by an anisotropic transformation. + */ + class TrsfCurve2d : public Adaptor2d_Curve2d + { + + public: + + /** + * Constructor. Initializes the object with the transformation parameters. + * Input parameters are not checked for validity. It is under responsibility + * of the caller. + */ + Standard_EXPORT TrsfCurve2d(const Handle(Geom2d_Curve) &theCurve, + const Trsf2d &theTrsf); + + /** + * Constructor. Initializes the object with the curve, first and last + * parameters and transformation. Input parameters are not checked + * for validity. It is under responsibility of the caller. + */ + Standard_EXPORT TrsfCurve2d(const Handle(Geom2d_Curve) &theCurve, + const Standard_Real theUFirst, + const Standard_Real theULast, + const Trsf2d &theTrsf); + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Real FirstParameter() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Real LastParameter() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT const Handle(Geom2d_Curve)& Curve() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT GeomAbs_CurveType GetType() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT void Load(const Handle(Geom2d_Curve) &C); + + /** + * Redefined method from the base class. + */ + Standard_EXPORT void Load(const Handle(Geom2d_Curve) &C, + const Standard_Real UFirst, + const Standard_Real ULast); + + /** + * Redefined method from the base class. + */ + Standard_EXPORT GeomAbs_Shape Continuity() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Integer NbIntervals(const GeomAbs_Shape S) const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT void Intervals(TColStd_Array1OfReal &T, + const GeomAbs_Shape S) const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Handle(Adaptor2d_HCurve2d) Trim + (const Standard_Real First, const Standard_Real Last, + const Standard_Real ) const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Boolean IsClosed() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Boolean IsPeriodic() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Real Period() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT gp_Pnt2d Value(const Standard_Real U) const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT void D0(const Standard_Real U, gp_Pnt2d &P) const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT void D1(const Standard_Real U, + gp_Pnt2d &P, gp_Vec2d &V) const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT void D2(const Standard_Real U, gp_Pnt2d &P, + gp_Vec2d &V1, gp_Vec2d &V2) const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT void D3(const Standard_Real U, gp_Pnt2d &P, + gp_Vec2d &V1, gp_Vec2d &V2, gp_Vec2d &V3) const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT gp_Vec2d DN(const Standard_Real U, + const Standard_Integer N) const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Real Resolution(const Standard_Real Ruv) const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT gp_Lin2d Line() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT gp_Circ2d Circle() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT gp_Elips2d Ellipse() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT gp_Hypr2d Hyperbola() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT gp_Parab2d Parabola() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Integer Degree() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Boolean IsRational() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Integer NbPoles() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Integer NbKnots() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Handle(Geom2d_BezierCurve) Bezier() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Handle(Geom2d_BSplineCurve) BSpline() const; + + /** + * Redefined method from the base class. + */ + Standard_EXPORT Standard_Integer NbSamples() const; + + private: + + Geom2dAdaptor_Curve myCurve; + Trsf2d myTrsf; + + }; +} + +#endif diff --git a/src/GEOM_I/GEOM_ITransformOperations_i.cc b/src/GEOM_I/GEOM_ITransformOperations_i.cc index 2281957e3..c18c87b6c 100644 --- a/src/GEOM_I/GEOM_ITransformOperations_i.cc +++ b/src/GEOM_I/GEOM_ITransformOperations_i.cc @@ -1392,3 +1392,37 @@ GEOM::GEOM_Object_ptr GEOM_ITransformOperations_i::RecomputeObject return aGEOMObject._retn(); } + +//============================================================================= +/*! + * MakeProjectionOnCylinder + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_ITransformOperations_i::MakeProjectionOnCylinder + (GEOM::GEOM_Object_ptr theObject, + CORBA::Double theRadius, + CORBA::Double theStartAngle, + CORBA::Double theAngleLength) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the object + Handle(GEOM_Object) anObject = GetObjectImpl(theObject); + + if (anObject.IsNull()) { + return aGEOMObject._retn(); + } + + //Perform the transformation + Handle(GEOM_Object) aResObject = GetOperations()->MakeProjectionOnCylinder + (anObject, theRadius, theStartAngle, theAngleLength); + + if (!GetOperations()->IsDone() || aResObject.IsNull()) { + return aGEOMObject._retn(); + } + + return GetObject(aResObject); +} diff --git a/src/GEOM_I/GEOM_ITransformOperations_i.hh b/src/GEOM_I/GEOM_ITransformOperations_i.hh index 40a5903ed..e507c1f77 100644 --- a/src/GEOM_I/GEOM_ITransformOperations_i.hh +++ b/src/GEOM_I/GEOM_ITransformOperations_i.hh @@ -197,6 +197,11 @@ class GEOM_I_EXPORT GEOM_ITransformOperations_i : GEOM::GEOM_Object_ptr RecomputeObject (GEOM::GEOM_Object_ptr theObject); + GEOM::GEOM_Object_ptr MakeProjectionOnCylinder + (GEOM::GEOM_Object_ptr theObject, + CORBA::Double theRadius, + CORBA::Double theStartAngle, + CORBA::Double theAngleLength); ::GEOMImpl_ITransformOperations* GetOperations() { return (::GEOMImpl_ITransformOperations*)GetImpl(); } }; diff --git a/src/GEOM_SWIG/GEOM_TestAll.py b/src/GEOM_SWIG/GEOM_TestAll.py index 3aa3eff61..683918508 100644 --- a/src/GEOM_SWIG/GEOM_TestAll.py +++ b/src/GEOM_SWIG/GEOM_TestAll.py @@ -272,6 +272,7 @@ def TestAll (geompy, math): Position2 = geompy.PositionAlongPath(Box, Arc, 0.5, 1, 0) #(2 GEOM_Object, 1 Double, 2 Bool)->GEOM_Object Offset = geompy.MakeOffset(Box, 10.) #(GEOM_Object, Double)->GEOM_Object ProjOnWire = geompy.MakeProjectionOnWire(p0, Wire) + ProjOnCyl = geompy.MakeProjectionOnCylinder(Wire, 100) Orientation = geompy.ChangeOrientation(Box) ExtEdge = geompy.ExtendEdge(Edge1, -0.3, 1.3) ExtFace = geompy.ExtendFace(Face5, -0.3, 1.3, -0.1, 1.1) @@ -497,6 +498,7 @@ def TestAll (geompy, math): id_Offset = geompy.addToStudy(Offset, "Offset") id_Orientation = geompy.addToStudy(Orientation, "Orientation") id_ProjOnWire = geompy.addToStudy(ProjOnWire[1], "ProjOnWire") + id_ProjOnCyl = geompy.addToStudy(ProjOnCyl, "ProjOnCyl") id_ExtEdge = geompy.addToStudy(ExtEdge, "ExtendedEdge") id_ExtFace = geompy.addToStudy(ExtFace, "ExtendedFace") id_Surface = geompy.addToStudy(Surface, "Surface From Face") diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index 531c1bf18..5287a1194 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -9403,6 +9403,67 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): anObj = self.MultiRotate2DByStep(aShape, aVec, anAngle, nbtimes1, aStep, nbtimes2, theName) return anObj + ## + # Compute a wire or a face that represents a projection of the source + # shape onto cylinder. The cylinder's coordinate system is the same + # as the global coordinate system. + # + # @param theObject The object to be projected. It can be either + # a planar wire or a face. + # @param theRadius The radius of the cylinder. + # @param theStartAngle The starting angle in radians from + # the cylinder's X axis around Z axis. The angle from which + # the projection is started. + # @param theAngleLength The projection length angle in radians. + # The angle in which to project the total length of the wire. + # If it is negative the projection is not scaled and natural + # wire length is kept for the projection. + # @param theName Object name; when specified, this parameter is used + # for result publication in the study. Otherwise, if automatic + # publication is switched on, default value is used for result name. + # + # @return New GEOM.GEOM_Object, containing the result shape. The result + # represents a wire or a face that represents a projection of + # the source shape onto a cylinder. + # + # @ref tui_projection "Example" + def MakeProjectionOnCylinder (self, theObject, theRadius, + theStartAngle=0.0, theAngleLength=-1.0, + theName=None): + """ + Compute a wire or a face that represents a projection of the source + shape onto cylinder. The cylinder's coordinate system is the same + as the global coordinate system. + + Parameters: + theObject The object to be projected. It can be either + a planar wire or a face. + theRadius The radius of the cylinder. + theStartAngle The starting angle in radians from the cylinder's X axis + around Z axis. The angle from which the projection is started. + theAngleLength The projection length angle in radians. The angle in which + to project the total length of the wire. If it is negative the + projection is not scaled and natural wire length is kept for + the projection. + theName Object name; when specified, this parameter is used + for result publication in the study. Otherwise, if automatic + publication is switched on, default value is used for result name. + + Returns: + New GEOM.GEOM_Object, containing the result shape. The result + represents a wire or a face that represents a projection of + the source shape onto a cylinder. + """ + # Example: see GEOM_TestAll.py + theRadius, theStartAngle, theAngleLength, Parameters = ParseParameters( + theRadius, theStartAngle, theAngleLength) + anObj = self.TrsfOp.MakeProjectionOnCylinder(theObject, theRadius, + theStartAngle, theAngleLength) + RaiseIfFailed("MakeProjectionOnCylinder", self.TrsfOp) + anObj.SetParameters(Parameters) + self._autoPublish(anObj, theName, "projection") + return anObj + # end of l3_transform ## @} diff --git a/src/TransformationGUI/CMakeLists.txt b/src/TransformationGUI/CMakeLists.txt index e60a2e84b..2b4b75858 100755 --- a/src/TransformationGUI/CMakeLists.txt +++ b/src/TransformationGUI/CMakeLists.txt @@ -75,6 +75,7 @@ SET(TransformationGUI_HEADERS TransformationGUI_ScaleDlg.h TransformationGUI_OffsetDlg.h TransformationGUI_ProjectionDlg.h + TransformationGUI_ProjectionOnCylDlg.h TransformationGUI_PositionDlg.h ) @@ -89,6 +90,7 @@ SET(_moc_HEADERS TransformationGUI_ScaleDlg.h TransformationGUI_OffsetDlg.h TransformationGUI_ProjectionDlg.h + TransformationGUI_ProjectionOnCylDlg.h TransformationGUI_PositionDlg.h ) @@ -111,6 +113,7 @@ SET(TransformationGUI_SOURCES TransformationGUI_ScaleDlg.cxx TransformationGUI_OffsetDlg.cxx TransformationGUI_ProjectionDlg.cxx + TransformationGUI_ProjectionOnCylDlg.cxx TransformationGUI_PositionDlg.cxx ${_moc_SOURCES} ${_uic_files} diff --git a/src/TransformationGUI/TransformationGUI.cxx b/src/TransformationGUI/TransformationGUI.cxx index 47be80cd1..943e2126b 100644 --- a/src/TransformationGUI/TransformationGUI.cxx +++ b/src/TransformationGUI/TransformationGUI.cxx @@ -49,6 +49,7 @@ #include "TransformationGUI_OffsetDlg.h" // Method OFFSET #include "TransformationGUI_ProjectionDlg.h" // Method PROJECTION #include "TransformationGUI_PositionDlg.h" // Method POSITION +#include "TransformationGUI_ProjectionOnCylDlg.h" // Method PROJECTION ON CYLINDER //======================================================================= // function : TransformationGUI() @@ -102,6 +103,9 @@ bool TransformationGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) case GEOMOp::OpProjection: // PROJECTION aDlg = new TransformationGUI_ProjectionDlg( getGeometryGUI(), parent ); break; + case GEOMOp::OpProjOnCyl: // PROJECTION ON CYLINDER + aDlg = new TransformationGUI_ProjectionOnCylDlg( getGeometryGUI(), parent ); + break; case GEOMOp::OpMultiTranslate: // MULTI TRANSLATION aDlg = new TransformationGUI_MultiTranslationDlg( getGeometryGUI(), parent ); break; diff --git a/src/TransformationGUI/TransformationGUI_ProjectionOnCylDlg.cxx b/src/TransformationGUI/TransformationGUI_ProjectionOnCylDlg.cxx new file mode 100644 index 000000000..d3efac641 --- /dev/null +++ b/src/TransformationGUI/TransformationGUI_ProjectionOnCylDlg.cxx @@ -0,0 +1,360 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : TransformationGUI_ProjectionOnCylDlg.cxx +// Author : Sergey KHROMOV, Open CASCADE S.A.S. + +#include "TransformationGUI_ProjectionOnCylDlg.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +//================================================================================= +// class : TransformationGUI_ProjectionOnCylDlg() +// purpose : Constructs a TransformationGUI_ProjectionOnCylDlg which is +// a child of 'parent', with the name 'name' and widget flags set to +// 'f'. The dialog will by default be modeless, unless you set +// 'modal' to TRUE to construct a modal dialog. +//================================================================================= +TransformationGUI_ProjectionOnCylDlg::TransformationGUI_ProjectionOnCylDlg +(GeometryGUI* theGeometryGUI, QWidget* parent, bool modal, Qt::WindowFlags fl) + : GEOMBase_Skeleton (theGeometryGUI, parent, modal, fl), + myObjectName (0), + mySelButton (0), + myRadiusSpin (0), + myStartAngleSpin (0), + myUseAngleLen (0), + myAngleLenSpin (0) +{ + SUIT_ResourceMgr* aResMgr = myGeomGUI->getApp()->resourceMgr(); + QPixmap image0 (aResMgr->loadPixmap("GEOM", tr("ICO_DLG_PROJ_ON_CYL"))); + QPixmap image1 (aResMgr->loadPixmap("GEOM", tr("ICON_SELECT"))); + + setWindowTitle(tr("GEOM_PROJ_ON_CYL_TITLE")); + + /***************************************************************/ + mainFrame()->GroupConstructors->setTitle(tr("GEOM_PROJECTION_TITLE")); + mainFrame()->RadioButton1->setIcon(image0); + mainFrame()->RadioButton2->setAttribute(Qt::WA_DeleteOnClose); + mainFrame()->RadioButton2->close(); + mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose); + mainFrame()->RadioButton3->close(); + + QGroupBox *aGrpParams = + new QGroupBox(tr("GEOM_ARGUMENTS"), centralWidget()); + QGridLayout *aParamsLayout = new QGridLayout(aGrpParams); + QLabel *anObjLbl = new QLabel(tr("GEOM_OBJECT"), aGrpParams); + QLabel *aRadiusLbl = new QLabel(tr("GEOM_RADIUS"), aGrpParams); + QLabel *aStartAngleLbl = + new QLabel(tr("GEOM_PROJ_ON_CYL_START_ANGLE"), aGrpParams); + QLabel *anAngleLenLbl = + new QLabel(tr("GEOM_PROJ_ON_CYL_LENGTH_ANGLE"), aGrpParams); + + myObjectName = new QLineEdit(aGrpParams); + mySelButton = new QPushButton(aGrpParams); + myRadiusSpin = new SalomeApp_DoubleSpinBox(aGrpParams); + myStartAngleSpin = new SalomeApp_DoubleSpinBox(aGrpParams); + myUseAngleLen = new QCheckBox(aGrpParams); + myAngleLenSpin = new SalomeApp_DoubleSpinBox(aGrpParams); + + myObjectName->setReadOnly(true); + mySelButton->setIcon(image1); + mySelButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + myUseAngleLen->setChecked(false); + + aParamsLayout->setMargin(9); + aParamsLayout->setSpacing(6); + aParamsLayout->addWidget(anObjLbl, 0, 1); + aParamsLayout->addWidget(mySelButton, 0, 2); + aParamsLayout->addWidget(myObjectName, 0, 3); + aParamsLayout->addWidget(aRadiusLbl, 1, 1); + aParamsLayout->addWidget(myRadiusSpin, 1, 2, 1, 2); + aParamsLayout->addWidget(aStartAngleLbl, 2, 1); + aParamsLayout->addWidget(myStartAngleSpin, 2, 2, 1, 2); + aParamsLayout->addWidget(myUseAngleLen, 3, 0); + aParamsLayout->addWidget(anAngleLenLbl, 3, 1); + aParamsLayout->addWidget(myAngleLenSpin, 3, 2, 1, 2); + + QVBoxLayout* layout = new QVBoxLayout( centralWidget() ); + layout->setMargin( 0 ); layout->setSpacing( 6 ); + layout->addWidget( aGrpParams ); + + /***************************************************************/ + + setHelpFileName("projection_on_cylinder_operation_page.html"); + + Init(); +} + +//================================================================================= +// function : ~TransformationGUI_ProjectionOnCylDlg() +// purpose : Destroys the object and frees any allocated resources +//================================================================================= +TransformationGUI_ProjectionOnCylDlg::~TransformationGUI_ProjectionOnCylDlg() +{ + // no need to delete child widgets, Qt does it all for us +} + +//================================================================================= +// function : Init() +// purpose : +//================================================================================= +void TransformationGUI_ProjectionOnCylDlg::Init() +{ + showOnlyPreviewControl(); + + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + double aStep = resMgr->doubleValue("Geometry", "SettingsGeomStep", 100); + double aSpecificStep = 5; + double aRadius = 100.0; + double aStartAngle = 0.; + double anAngleLen = 360.; + + initSpinBox(myRadiusSpin, 0.00001, COORD_MAX, aStep, "length_precision"); + initSpinBox(myStartAngleSpin, -180., 180., aSpecificStep, "angle_precision"); + initSpinBox(myAngleLenSpin, 0.00001, COORD_MAX, aSpecificStep, "angle_precision"); + + myRadiusSpin->setValue(aRadius); + myStartAngleSpin->setValue(aStartAngle); + myAngleLenSpin->setValue(anAngleLen); + + myObjectName->setText(""); + myUseAngleLen->setChecked(true); + + // signals and slots connections + connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk())); + connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply())); + + connect(mySelButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + connect(myRadiusSpin, SIGNAL(valueChanged(double)), this, SLOT(processPreview())); + connect(myStartAngleSpin, SIGNAL(valueChanged(double)), this, SLOT(processPreview())); + connect(myAngleLenSpin, SIGNAL(valueChanged(double)), this, SLOT(processPreview())); + connect(myUseAngleLen, SIGNAL(clicked()), this, SLOT(SetUseLengthAngle())); + + connect(myGeomGUI->getApp()->selectionMgr(),SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); + + initName(tr("GEOM_PROJECTION_NAME")); + + buttonOk()->setEnabled(false); + buttonApply()->setEnabled(false); + + activateSelection(); + SelectionIntoArgument(); +} + +//================================================================================= +// function : ClickOnOk() +// purpose : +//================================================================================= +void TransformationGUI_ProjectionOnCylDlg::ClickOnOk() +{ + setIsApplyAndClose( true ); + if (ClickOnApply()) + ClickOnCancel(); +} + +//================================================================================= +// function : ClickOnApply() +// purpose : +//================================================================================= +bool TransformationGUI_ProjectionOnCylDlg::ClickOnApply() +{ + if ( !onAccept() ) + return false; + + initName(); + return true; +} + +//================================================================================= +// function : SelectionIntoArgument() +// purpose : Called when selection is changed or on dialog initialization or activation +//================================================================================= +void TransformationGUI_ProjectionOnCylDlg::SelectionIntoArgument() +{ + erasePreview(); + myObj = GEOM::GEOM_Object::_nil(); + + LightApp_SelectionMgr* aSelMgr = myGeomGUI->getApp()->selectionMgr(); + SALOME_ListIO aSelList; + aSelMgr->selectedObjects(aSelList); + + if (aSelList.Extent() == 1) { + // Single object is selected. + GEOM::GEOM_Object_var aSelectedObject = + GEOMBase::ConvertIOinGEOMObject( aSelList.First() ); + + if (aSelectedObject->_is_nil()) { + // Null object. + myObjectName->setText(""); + buttonOk()->setEnabled(false); + buttonApply()->setEnabled(false); + } else { + // Not Null object. + myObj = aSelectedObject; + myObjectName->setText(GEOMBase::GetName(myObj)); + buttonOk()->setEnabled(true); + buttonApply()->setEnabled(true); + } + } else { + // Not a single object is selected. + myObjectName->setText(""); + buttonOk()->setEnabled(false); + buttonApply()->setEnabled(false); + } + + processPreview(); +} + +//================================================================================= +// function : SetEditCurrentArgument() +// purpose : +//================================================================================= +void TransformationGUI_ProjectionOnCylDlg::SetEditCurrentArgument() +{ + myObjectName->setFocus(); + myEditCurrentArgument = myObjectName; + SelectionIntoArgument(); +} + +//================================================================================= +// function : SetUseLengthAngle() +// purpose : +//================================================================================= +void TransformationGUI_ProjectionOnCylDlg::SetUseLengthAngle() +{ + myAngleLenSpin->setEnabled(myUseAngleLen->isChecked()); + processPreview(); +} + +//================================================================================= +// function : activateSelection +// purpose : activate selection of wires or faces +//================================================================================= +void TransformationGUI_ProjectionOnCylDlg::activateSelection() +{ + TColStd_MapOfInteger aMap; + + aMap.Add(GEOM_WIRE); + aMap.Add(GEOM_FACE); + globalSelection(aMap); +} + +//================================================================================= +// function : ActivateThisDialog() +// purpose : +//================================================================================= +void TransformationGUI_ProjectionOnCylDlg::ActivateThisDialog() +{ + GEOMBase_Skeleton::ActivateThisDialog(); + connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ), + this, SLOT( SelectionIntoArgument() ) ); + + activateSelection(); +} + +//================================================================================= +// function : enterEvent() +// purpose : +//================================================================================= +void TransformationGUI_ProjectionOnCylDlg::enterEvent (QEvent*) +{ + if (!mainFrame()->GroupConstructors->isEnabled()) + ActivateThisDialog(); +} + +//================================================================================= +// function : createOperation +// purpose : +//================================================================================= +GEOM::GEOM_IOperations_ptr TransformationGUI_ProjectionOnCylDlg::createOperation() +{ + return getGeomEngine()->GetITransformOperations(getStudyId()); +} + +//================================================================================= +// function : isValid +// purpose : +//================================================================================= +bool TransformationGUI_ProjectionOnCylDlg::isValid (QString &msg) +{ + bool isOk = false; + + if (!myObj->_is_nil() && + myRadiusSpin->isValid(msg, !IsPreview()) && + myStartAngleSpin->isValid(msg, !IsPreview())) { + if (myUseAngleLen->isChecked()) { + // Check length angle spin. + isOk = myAngleLenSpin->isValid(msg, !IsPreview()); + } else { + // Don't check length angle spin. + isOk = true; + } + } + + return isOk; +} + +//================================================================================= +// function : execute +// purpose : +//================================================================================= +bool TransformationGUI_ProjectionOnCylDlg::execute (ObjectList& objects) +{ + GEOM::GEOM_ITransformOperations_var anOper = + GEOM::GEOM_ITransformOperations::_narrow(getOperation()); + + double aRadius = myRadiusSpin->value(); + double aStartAngle = myStartAngleSpin->value()*M_PI/180.; + double aLengthAngle = -1.; + + if (myUseAngleLen->isChecked()) { + aLengthAngle = myAngleLenSpin->value()*M_PI/180.; + } + + GEOM::GEOM_Object_var anObj = anOper->MakeProjectionOnCylinder + (myObj, aRadius, aStartAngle, aLengthAngle); + + if (!anObj->_is_nil()) { + objects.push_back(anObj._retn()); + } + + return true; +} diff --git a/src/TransformationGUI/TransformationGUI_ProjectionOnCylDlg.h b/src/TransformationGUI/TransformationGUI_ProjectionOnCylDlg.h new file mode 100644 index 000000000..beb16d976 --- /dev/null +++ b/src/TransformationGUI/TransformationGUI_ProjectionOnCylDlg.h @@ -0,0 +1,78 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : TransformationGUI_ProjectionOnCylDlg.h +// Author : Sergey KHROMOV, Open CASCADE S.A.S. +// +#ifndef TRANSFORMATIONGUI_PROJECTIONONCYLDLG_H +#define TRANSFORMATIONGUI_PROJECTIONONCYLDLG_H + + +#include "GEOMBase_Skeleton.h" + + +//================================================================================= +// class : TransformationGUI_ProjectionOnCylDlg +// purpose : +//================================================================================= +class TransformationGUI_ProjectionOnCylDlg : public GEOMBase_Skeleton +{ + Q_OBJECT + +public: + TransformationGUI_ProjectionOnCylDlg(GeometryGUI*, QWidget* = 0, + bool = false, Qt::WindowFlags = 0); + ~TransformationGUI_ProjectionOnCylDlg(); + +protected: + // redefined from GEOMBase_Helper + virtual GEOM::GEOM_IOperations_ptr createOperation(); + virtual bool isValid(QString &msg); + virtual bool execute(ObjectList &); + +private: + void Init(); + void enterEvent( QEvent* ); + void activateSelection(); + +private slots: + void ClickOnOk(); + bool ClickOnApply(); + void ActivateThisDialog(); + void SelectionIntoArgument(); + void SetEditCurrentArgument(); + void SetUseLengthAngle(); + +private: + + GEOM::GEOM_Object_var myObj; + QLineEdit *myObjectName; + QPushButton *mySelButton; + SalomeApp_DoubleSpinBox *myRadiusSpin; + SalomeApp_DoubleSpinBox *myStartAngleSpin; + QCheckBox *myUseAngleLen; + SalomeApp_DoubleSpinBox *myAngleLenSpin; + +}; + +#endif // TRANSFORMATIONGUI_PROJECTIONONCYLDLG_H -- 2.39.2