0022776: [CEA 1269] Project a wire or a face on a cylinder: add rotation angle

This commit is contained in:
skv 2015-06-08 13:06:39 +03:00
parent fe74d236e0
commit ce07ba70be
15 changed files with 147 additions and 49 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -18,19 +18,27 @@ the angle of the projection start.
- <b>Length angle</b> where the total length of
the wire should be projected. If it is unchecked the projection is not scaled and the natural
wire length is kept for the projection.
- <b>Rotation angle</b> the desired angle between the tangent vector to
the first curve at the first point of the theObject's projection in 2D space
and U-direction of cylinder's 2D space.
- \ref restore_presentation_parameters_page "Advanced options".
\image html proj_on_cyl_dlg.png
\n The following figure explains meaning of each input angle:
\image html proj_on_cyl_angles.png "Input angles of projection on the cylinder"
\n <b>Example:</b>
\image html proj_on_cyl_preview.png "The curve (in red) and its projection on the cylinder"
\n <b>TUI Command:</b> <em>geompy.MakeProjectionOnCylinder(theObject, theRadius,
theStartAngle=0.0, theAngleLength=-1.0),</em>
theStartAngle=0.0, theAngleLength=-1.0, theAngleRotation=0.0),</em>
where \em theObject is a shape to be projected, \em theRadius
is a cylinder radius, \em theStartAngle is the starting angle of projection in
radians, \em theAngleLength the projection length angle in radians.
radians, \em theAngleLength the projection length angle in radians,
\em theAngleRotation projection rotation angle in radians.
The \em Result will be a \em GEOM_Object.
Our <b>TUI Scripts</b> provide you with useful examples of the use of

View File

@ -1439,13 +1439,17 @@ module GEOM
* 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 theAngleRotation the desired angle between the tangent vector
* to the first curve at the first point of the theObject's
* projection in 2D space and U-direction of cylinder's 2D space.
* \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);
in double theAngleLength,
in double theAngleRotation);
};
/*!

View File

@ -7572,5 +7572,9 @@ Do you want to create new material?</translation>
<source>GEOM_PROJ_ON_CYL_LENGTH_ANGLE</source>
<translation>Length angle</translation>
</message>
<message>
<source>GEOM_PROJ_ON_CYL_ROTATION_ANGLE</source>
<translation>Rotation angle</translation>
</message>
</context>
</TS>

View File

@ -28,6 +28,7 @@
#define PROJCYL_ARG_RADIUS 2
#define PROJCYL_ARG_START_ANGLE 3
#define PROJCYL_ARG_ANGLE_LENGTH 4
#define PROJCYL_ARG_ANGLE_ROTATION 5
class GEOMImpl_IProjOnCyl
{
@ -36,14 +37,16 @@ public:
GEOMImpl_IProjOnCyl(Handle(GEOM_Function) theFunction): _func(theFunction) {}
void SetShape (const Handle(GEOM_Function) &theShape)
{ _func->SetReference(PROJCYL_ARG_SHAPE, theShape); }
void SetRadius (const Standard_Real theRadius)
{ _func->SetReal(PROJCYL_ARG_RADIUS, theRadius); }
void SetStartAngle (const Standard_Real theStartAngle)
{ _func->SetReal(PROJCYL_ARG_START_ANGLE, theStartAngle); }
void SetAngleLength (const Standard_Real theAngleLength)
{ _func->SetReal(PROJCYL_ARG_ANGLE_LENGTH, theAngleLength); }
void SetShape (const Handle(GEOM_Function) &theShape)
{ _func->SetReference(PROJCYL_ARG_SHAPE, theShape); }
void SetRadius (const Standard_Real theRadius)
{ _func->SetReal(PROJCYL_ARG_RADIUS, theRadius); }
void SetStartAngle (const Standard_Real theStartAngle)
{ _func->SetReal(PROJCYL_ARG_START_ANGLE, theStartAngle); }
void SetAngleLength (const Standard_Real theAngleLength)
{ _func->SetReal(PROJCYL_ARG_ANGLE_LENGTH, theAngleLength); }
void SetAngleRotation (const Standard_Real theAngleLength)
{ _func->SetReal(PROJCYL_ARG_ANGLE_ROTATION, theAngleLength); }
Handle(GEOM_Function) GetShape()
{ return _func->GetReference(PROJCYL_ARG_SHAPE); }
@ -53,6 +56,8 @@ public:
{ return _func->GetReal(PROJCYL_ARG_START_ANGLE ); }
Standard_Real GetAngleLength()
{ return _func->GetReal(PROJCYL_ARG_ANGLE_LENGTH ); }
Standard_Real GetAngleRotation()
{ return _func->GetReal(PROJCYL_ARG_ANGLE_ROTATION ); }
private:

View File

@ -2278,7 +2278,8 @@ Handle(GEOM_Object) GEOMImpl_ITransformOperations::MakeProjectionOnCylinder
(const Handle(GEOM_Object) &theObject,
const Standard_Real theRadius,
const Standard_Real theStartAngle,
const Standard_Real theAngleLength)
const Standard_Real theAngleLength,
const Standard_Real theAngleRotation)
{
SetErrorCode(KO);
@ -2312,6 +2313,7 @@ Handle(GEOM_Object) GEOMImpl_ITransformOperations::MakeProjectionOnCylinder
aProj.SetRadius(theRadius);
aProj.SetStartAngle(theStartAngle);
aProj.SetAngleLength(theAngleLength);
aProj.SetAngleRotation(theAngleRotation);
//Compute the Projection
try {
@ -2328,16 +2330,10 @@ Handle(GEOM_Object) GEOMImpl_ITransformOperations::MakeProjectionOnCylinder
}
//Make a Python command
GEOM::TPythonDump pd(aFunction);
pd << aResult << " = geompy.MakeProjectionOnCylinder("
<< theObject << ", " << theRadius << ", " << theStartAngle;
if (theAngleLength >= 0.) {
pd << ", " << theAngleLength;
}
pd << ")";
GEOM::TPythonDump(aFunction)
<< aResult << " = geompy.MakeProjectionOnCylinder("
<< theObject << ", " << theRadius << ", " << theStartAngle
<< ", " << theAngleLength << ", " << theAngleRotation << ")";
SetErrorCode(OK);

View File

@ -195,7 +195,8 @@ class GEOMImpl_ITransformOperations : public GEOM_IOperations
(const Handle(GEOM_Object) &theObject,
const Standard_Real theRadius,
const Standard_Real theStartAngle,
const Standard_Real theAngleLength);
const Standard_Real theAngleLength,
const Standard_Real theAngleRotation);
};

View File

@ -33,6 +33,8 @@
#include <GEOMUtils_HTrsfCurve2d.hxx>
#include <Approx_Curve2d.hxx>
#include <Bnd_Box2d.hxx>
#include <BndLib_Add2dCurve.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve2d.hxx>
#include <BRepBuilderAPI_Transform.hxx>
@ -428,10 +430,11 @@ Standard_Integer GEOMImpl_ProjectionDriver::Execute(TFunction_Logbook& log) cons
}
// 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();
const TopAbs_ShapeEnum aType = aShape.ShapeType();
const Standard_Real aRadius = aProj.GetRadius();
const Standard_Real aStartAngle = aProj.GetStartAngle();
const Standard_Real aLengthAngle = aProj.GetAngleLength();
const Standard_Real aRotationAngle = aProj.GetAngleRotation();
if (aType != TopAbs_WIRE && aType != TopAbs_FACE) {
return 0;
@ -441,8 +444,8 @@ Standard_Integer GEOMImpl_ProjectionDriver::Execute(TFunction_Logbook& log) cons
return 0;
}
TopoDS_Shape aProjShape =
projectOnCylinder(aShape, aRadius, aStartAngle, aLengthAngle);
TopoDS_Shape aProjShape = projectOnCylinder
(aShape, aRadius, aStartAngle, aLengthAngle, aRotationAngle);
if (aProjShape.IsNull()) {
return 0;
@ -504,6 +507,8 @@ GetCreationInformation(std::string& theOperationName,
AddParam(theParams, "Length angle", aLengthAngle);
}
AddParam(theParams, "Rotation angle", aProj.GetAngleRotation());
break;
}
default:
@ -523,7 +528,8 @@ TopoDS_Shape GEOMImpl_ProjectionDriver::projectOnCylinder
(const TopoDS_Shape &theShape,
const Standard_Real theRadius,
const Standard_Real theStartAngle,
const Standard_Real theAngleLength) const
const Standard_Real theAngleLength,
const Standard_Real theAngleRotation) const
{
TopoDS_Shape aResult;
@ -596,8 +602,6 @@ TopoDS_Shape GEOMImpl_ProjectionDriver::projectOnCylinder
// 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()) {
@ -605,21 +609,63 @@ TopoDS_Shape GEOMImpl_ProjectionDriver::projectOnCylinder
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]);
// Rotate 2D presentation of face.
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);
gp_Pnt2d aPntUV;
gp_Vec2d aVecUV;
gp_Vec2d aVecU0(1., 0);
anAdaptorCurve.D1(aParam, aPntUV, aVecUV);
if (aVecUV.Magnitude() <= gp::Resolution()) {
return aResult;
}
if (aFirstEdge.Orientation() == TopAbs_REVERSED) {
aVecUV.Reverse();
}
const Standard_Real anAngle = aVecUV.Angle(aVecU0) + theAngleRotation;
const Standard_Boolean isToRotate = Abs(anAngle) > Precision::Angular();
gp_Trsf2d aRotTrsf;
Bnd_Box2d aUVBox;
Standard_Real aPar[2];
if (isToRotate) {
aRotTrsf.SetRotation(aPntUV, anAngle);
}
for (; aOWExp.More(); aOWExp.Next()) {
TopoDS_Edge anEdge = aOWExp.Current();
Handle(Geom2d_Curve) aCurve =
BRep_Tool::CurveOnSurface(anEdge, aFace, aPar[0], aPar[1]);
if (aCurve.IsNull()) {
continue;
}
if (isToRotate) {
aCurve = Handle(Geom2d_Curve)::DownCast(aCurve->Transformed(aRotTrsf));
}
BndLib_Add2dCurve::Add(aCurve, aPar[0], aPar[1], 0., aUVBox);
}
Standard_Real aU[2];
Standard_Real aV[2];
aUVBox.Get(aU[0], aV[0], aU[1], aV[1]);
// Compute anisotropic transformation from a face's 2d space
// to cylinder's 2d space.
GEOMUtils::Trsf2d aTrsf2d
(1./theRadius, 0., theStartAngle - aU[0]/theRadius,
0., 1., aPnt.Z() - 0.5*(aV[1] - aV[0]) - aPntUV.Y());
0., 1., aPnt.Z() - aPntUV.Y());
// Compute scaling trsf.
const Standard_Boolean isToScale = theAngleLength >= Precision::Angular();
@ -640,7 +686,6 @@ TopoDS_Shape GEOMImpl_ProjectionDriver::projectOnCylinder
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());
@ -659,6 +704,10 @@ TopoDS_Shape GEOMImpl_ProjectionDriver::projectOnCylinder
continue;
}
if (isToRotate) {
aCurve = Handle(Geom2d_Curve)::DownCast(aCurve->Transformed(aRotTrsf));
}
// Transform the curve to cylinder's parametric space.
GEOMUtils::Handle(HTrsfCurve2d) aTrsfCurve =
new GEOMUtils::HTrsfCurve2d(aCurve, aPar[0], aPar[1], aTrsf2d);

View File

@ -87,7 +87,8 @@ private:
TopoDS_Shape projectOnCylinder(const TopoDS_Shape &theShape,
const Standard_Real theRadius,
const Standard_Real theStartAngle,
const Standard_Real theAngleLength) const;
const Standard_Real theAngleLength,
const Standard_Real theAngleRotation) const;
public:

View File

@ -1402,7 +1402,8 @@ GEOM::GEOM_Object_ptr GEOM_ITransformOperations_i::MakeProjectionOnCylinder
(GEOM::GEOM_Object_ptr theObject,
CORBA::Double theRadius,
CORBA::Double theStartAngle,
CORBA::Double theAngleLength)
CORBA::Double theAngleLength,
CORBA::Double theAngleRotation)
{
GEOM::GEOM_Object_var aGEOMObject;
@ -1418,7 +1419,7 @@ GEOM::GEOM_Object_ptr GEOM_ITransformOperations_i::MakeProjectionOnCylinder
//Perform the transformation
Handle(GEOM_Object) aResObject = GetOperations()->MakeProjectionOnCylinder
(anObject, theRadius, theStartAngle, theAngleLength);
(anObject, theRadius, theStartAngle, theAngleLength, theAngleRotation);
if (!GetOperations()->IsDone() || aResObject.IsNull()) {
return aGEOMObject._retn();

View File

@ -201,7 +201,8 @@ class GEOM_I_EXPORT GEOM_ITransformOperations_i :
(GEOM::GEOM_Object_ptr theObject,
CORBA::Double theRadius,
CORBA::Double theStartAngle,
CORBA::Double theAngleLength);
CORBA::Double theAngleLength,
CORBA::Double theAngleRotation);
::GEOMImpl_ITransformOperations* GetOperations() { return (::GEOMImpl_ITransformOperations*)GetImpl(); }
};

View File

@ -9581,6 +9581,10 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
# 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 theAngleRotation The desired angle in radians between
# the tangent vector to the first curve at the first point of
# the theObject's projection in 2D space and U-direction of
# cylinder's 2D space.
# @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.
@ -9592,6 +9596,7 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
# @ref tui_projection "Example"
def MakeProjectionOnCylinder (self, theObject, theRadius,
theStartAngle=0.0, theAngleLength=-1.0,
theAngleRotation=0.0,
theName=None):
"""
Compute a wire or a face that represents a projection of the source
@ -9608,6 +9613,10 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
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.
theAngleRotation The desired angle in radians between
the tangent vector to the first curve at the first
point of the theObject's projection in 2D space and
U-direction of cylinder's 2D space.
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.
@ -9624,14 +9633,19 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
flagAngleLength = False
if isinstance(theAngleLength,str):
flagAngleLength = True
theRadius, theStartAngle, theAngleLength, Parameters = ParseParameters(
theRadius, theStartAngle, theAngleLength)
flagAngleRotation = False
if isinstance(theAngleRotation,str):
flagAngleRotation = True
theRadius, theStartAngle, theAngleLength, theAngleRotation, Parameters = ParseParameters(
theRadius, theStartAngle, theAngleLength, theAngleRotation)
if flagStartAngle:
theStartAngle = theStartAngle*math.pi/180.
if flagAngleLength:
theAngleLength = theAngleLength*math.pi/180.
if flagAngleRotation:
theAngleRotation = theAngleRotation*math.pi/180.
anObj = self.TrsfOp.MakeProjectionOnCylinder(theObject, theRadius,
theStartAngle, theAngleLength)
theStartAngle, theAngleLength, theAngleRotation)
RaiseIfFailed("MakeProjectionOnCylinder", self.TrsfOp)
anObj.SetParameters(Parameters)
self._autoPublish(anObj, theName, "projection")

View File

@ -60,7 +60,8 @@ TransformationGUI_ProjectionOnCylDlg::TransformationGUI_ProjectionOnCylDlg
myRadiusSpin (0),
myStartAngleSpin (0),
myUseAngleLen (0),
myAngleLenSpin (0)
myAngleLenSpin (0),
myAngleRotSpin (0)
{
SUIT_ResourceMgr* aResMgr = myGeomGUI->getApp()->resourceMgr();
QPixmap image0 (aResMgr->loadPixmap("GEOM", tr("ICO_DLG_PROJ_ON_CYL")));
@ -85,6 +86,8 @@ TransformationGUI_ProjectionOnCylDlg::TransformationGUI_ProjectionOnCylDlg
new QLabel(tr("GEOM_PROJ_ON_CYL_START_ANGLE"), aGrpParams);
QLabel *anAngleLenLbl =
new QLabel(tr("GEOM_PROJ_ON_CYL_LENGTH_ANGLE"), aGrpParams);
QLabel *anAngleRotLbl =
new QLabel(tr("GEOM_PROJ_ON_CYL_ROTATION_ANGLE"), aGrpParams);
myObjectName = new QLineEdit(aGrpParams);
mySelButton = new QPushButton(aGrpParams);
@ -92,6 +95,7 @@ TransformationGUI_ProjectionOnCylDlg::TransformationGUI_ProjectionOnCylDlg
myStartAngleSpin = new SalomeApp_DoubleSpinBox(aGrpParams);
myUseAngleLen = new QCheckBox(aGrpParams);
myAngleLenSpin = new SalomeApp_DoubleSpinBox(aGrpParams);
myAngleRotSpin = new SalomeApp_DoubleSpinBox(aGrpParams);
myObjectName->setReadOnly(true);
mySelButton->setIcon(image1);
@ -110,6 +114,8 @@ TransformationGUI_ProjectionOnCylDlg::TransformationGUI_ProjectionOnCylDlg
aParamsLayout->addWidget(myUseAngleLen, 3, 0);
aParamsLayout->addWidget(anAngleLenLbl, 3, 1);
aParamsLayout->addWidget(myAngleLenSpin, 3, 2, 1, 2);
aParamsLayout->addWidget(anAngleRotLbl, 4, 1);
aParamsLayout->addWidget(myAngleRotSpin, 4, 2, 1, 2);
QVBoxLayout* layout = new QVBoxLayout( centralWidget() );
layout->setMargin( 0 ); layout->setSpacing( 6 );
@ -145,14 +151,17 @@ void TransformationGUI_ProjectionOnCylDlg::Init()
double aRadius = 100.0;
double aStartAngle = 0.;
double anAngleLen = 360.;
double aRotAngle = 0.;
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");
initSpinBox(myAngleRotSpin, -180., 180., aSpecificStep, "angle_precision");
myRadiusSpin->setValue(aRadius);
myStartAngleSpin->setValue(aStartAngle);
myAngleLenSpin->setValue(anAngleLen);
myAngleRotSpin->setValue(aRotAngle);
myObjectName->setText("");
myUseAngleLen->setChecked(true);
@ -165,6 +174,7 @@ void TransformationGUI_ProjectionOnCylDlg::Init()
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(myAngleRotSpin, SIGNAL(valueChanged(double)), this, SLOT(processPreview()));
connect(myUseAngleLen, SIGNAL(clicked()), this, SLOT(SetUseLengthAngle()));
connect(myGeomGUI->getApp()->selectionMgr(),SIGNAL(currentSelectionChanged()),
@ -319,7 +329,8 @@ bool TransformationGUI_ProjectionOnCylDlg::isValid (QString &msg)
if (!myObj->_is_nil() &&
myRadiusSpin->isValid(msg, !IsPreview()) &&
myStartAngleSpin->isValid(msg, !IsPreview())) {
myStartAngleSpin->isValid(msg, !IsPreview()) &&
myAngleRotSpin->isValid(msg, !IsPreview())) {
if (myUseAngleLen->isChecked()) {
// Check length angle spin.
isOk = myAngleLenSpin->isValid(msg, !IsPreview());
@ -343,6 +354,7 @@ bool TransformationGUI_ProjectionOnCylDlg::execute (ObjectList& objects)
double aRadius = myRadiusSpin->value();
double aStartAngle = myStartAngleSpin->value()*M_PI/180.;
double aRotAngle = myAngleRotSpin->value()*M_PI/180.;
double aLengthAngle = -1.;
if (myUseAngleLen->isChecked()) {
@ -350,7 +362,7 @@ bool TransformationGUI_ProjectionOnCylDlg::execute (ObjectList& objects)
}
GEOM::GEOM_Object_var anObj = anOper->MakeProjectionOnCylinder
(myObj, aRadius, aStartAngle, aLengthAngle);
(myObj, aRadius, aStartAngle, aLengthAngle, aRotAngle);
if (!anObj->_is_nil()) {
if (!IsPreview()) {
@ -359,6 +371,7 @@ bool TransformationGUI_ProjectionOnCylDlg::execute (ObjectList& objects)
aParameters << myStartAngleSpin->text();
if (myUseAngleLen->isChecked())
aParameters << myAngleLenSpin->text();
aParameters << myAngleRotSpin->text();
anObj->SetParameters(aParameters.join(":").toUtf8().constData());
}
objects.push_back(anObj._retn());

View File

@ -72,6 +72,7 @@ private:
SalomeApp_DoubleSpinBox *myStartAngleSpin;
QCheckBox *myUseAngleLen;
SalomeApp_DoubleSpinBox *myAngleLenSpin;
SalomeApp_DoubleSpinBox *myAngleRotSpin;
};