- <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
* 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);
};
/*!
<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>
#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
{
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); }
{ 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:
(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);
aProj.SetRadius(theRadius);
aProj.SetStartAngle(theStartAngle);
aProj.SetAngleLength(theAngleLength);
+ aProj.SetAngleRotation(theAngleRotation);
//Compute the Projection
try {
}
//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);
(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);
};
#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>
}
// 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;
return 0;
}
- TopoDS_Shape aProjShape =
- projectOnCylinder(aShape, aRadius, aStartAngle, aLengthAngle);
+ TopoDS_Shape aProjShape = projectOnCylinder
+ (aShape, aRadius, aStartAngle, aLengthAngle, aRotationAngle);
if (aProjShape.IsNull()) {
return 0;
AddParam(theParams, "Length angle", aLengthAngle);
}
+ AddParam(theParams, "Rotation angle", aProj.GetAngleRotation());
+
break;
}
default:
(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;
// 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()) {
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();
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());
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);
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:
(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;
//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();
(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(); }
};
# 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.
# @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
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.
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")
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")));
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);
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);
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 );
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);
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()),
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());
double aRadius = myRadiusSpin->value();
double aStartAngle = myStartAngleSpin->value()*M_PI/180.;
+ double aRotAngle = myAngleRotSpin->value()*M_PI/180.;
double aLengthAngle = -1.;
if (myUseAngleLen->isChecked()) {
}
GEOM::GEOM_Object_var anObj = anOper->MakeProjectionOnCylinder
- (myObj, aRadius, aStartAngle, aLengthAngle);
+ (myObj, aRadius, aStartAngle, aLengthAngle, aRotAngle);
if (!anObj->_is_nil()) {
if (!IsPreview()) {
aParameters << myStartAngleSpin->text();
if (myUseAngleLen->isChecked())
aParameters << myAngleLenSpin->text();
+ aParameters << myAngleRotSpin->text();
anObj->SetParameters(aParameters.join(":").toUtf8().constData());
}
objects.push_back(anObj._retn());
SalomeApp_DoubleSpinBox *myStartAngleSpin;
QCheckBox *myUseAngleLen;
SalomeApp_DoubleSpinBox *myAngleLenSpin;
+ SalomeApp_DoubleSpinBox *myAngleRotSpin;
};