# How to rotate around pivot

#### mmaenz

##### CAD practitioner
Hi,

I don't understand how to make multiple transformations or how to rotate around a pivot to get a valid result. I'm not sure if it is a problem with the order in which it should happen or am I misunderstanding things how it is meant to work. The gp_Trsf seems to make one transformation at a time and therefor multiple gp_Trsf must be chained to get the result.

As per documentation of opencascade (https://dev.opencascade.org/doc/overview/html/occt_user_guides__modeling_data.html#occt_modat_5_1) I need to create a gp_Trsf for every transformation and chain them using TopLoc_Location.Multiplied().

This is what I do so far:

C++:
``````TopLoc_Location rotate(TopLoc_Location& world, double angle, int axis, gp_XYZ rotationPosition) {
gp_Quaternion RX(gp::DX(), 0.);
gp_Quaternion RY(gp::DY(), 0.);
gp_Quaternion RZ(gp::DZ(), 0.);

switch (axis) {
case 1: RX.Set(gp_Quaternion(gp::DX(), angle / 180 * M_PI)); break;
case 2: RY.Set(gp_Quaternion(gp::DY(), angle / 180 * M_PI)); break;
case 3: RZ.Set(gp_Quaternion(gp::DZ(), angle / 180 * M_PI)); break;
}

gp_Quaternion RA(RZ * RY * RX);

gp_Trsf compoundTransform = gp_Trsf(world);
TopLoc_Location result;

gp_XYZ compoundPosition = gp_XYZ(compoundTransform.TranslationPart());
gp_XYZ distanceToPivot = compoundPosition.Subtracted(rotationPosition);

// 0
TopLoc_Location compoundPositionLocation = TopLoc_Location(world);

// 1
// Bring object which should be rotated to actual rotate position
gp_Trsf rotationPositionTrsf;
rotationPositionTrsf.SetTranslation(rotationPosition);
TopLoc_Location rotationPositionLocation(rotationPositionTrsf);

// 2
// The rotation itsself
gp_Trsf rotationTrsf;
RA.Multiply(compoundTransform.GetRotation());
rotationTrsf.SetRotation(RA);
TopLoc_Location rotationLocation(rotationTrsf);

// 3
// Objekt auf die Differenz schieben vom eigentlichen Drehpunkt damit wieder auf Originalposition
gp_Trsf rotationCompoundDifferenceTrsf;
rotationCompoundDifferenceTrsf.SetTranslation(distanceToPivot);
TopLoc_Location rotationCompoundDifferenceLocation(rotationCompoundDifferenceTrsf);

result = compoundPositionLocation * rotationPositionLocation * rotationLocation * rotationCompoundDifferenceLocation;

return result;
}``````

This is the process in screenshots, the red arrow points to the pivot and the yellow to 0,0,0:

it works and looks like this when turning 90 degree on the pivot (25, 758, 33) and looks like this:

When doing the same with the opposite bracket assembly is won't work:

It already has a rotate information which I'm multiplying with when doing the rotate but the offset is not working. I tried quite a few different ways but it does not end in the location where it should be. I also suspect that I didn't understand how the rotation works?

I already had that question on occ forum but digged a little deeper since. If I've got an answer I will reply to both.

Any help or hint is appreciated...

Thanks!

#### natalia

##### Moderator
Staff member
Hi mmaenz,

Sorry that did not answer so long…
At last, I understand what your case is and what might be the solution for you.

Example of rotating AIS_Shape around a pivot exists in a ready presentation AIS_Manipulator in OCCT. When you investigate the code of it, I think, you find the solution. The pivot is the position given to the manipulator. Your case is ‘AIS_MM_Rotation’ processing.

The logic that you need to implement (if follow this way) is the next:
1. Preparing gp_Trsf that contains the location and angle. The lines of interest here are:
C++:
``````    case AIS_MM_Rotation:
{
const gp_Pnt aPosLoc   = myStartPosition.Location();
const gp_Ax1 aCurrAxis = getAx1FromAx2Dir (myStartPosition, myCurrentIndex);
...
gp_Trsf aNewTrsf;
aNewTrsf.SetRotation (aCurrAxis, anAngle);
...
}``````
2. Combine this transformation with the transformation of TopoDS_Shape/AIS_Shape. In your model (on attached snapshots), the brackets have own transformation, so you need to combine it with the new transformation. In AIS_Manipulator the code that relates to it is:
Code:
`````` void AIS_Manipulator::Transform (const gp_Trsf& theTrsf)
{
const Handle(AIS_InteractiveObject)& anObj = anObjIter.ChangeValue();
const gp_Trsf& anOldTrsf = aTrsfIter.Value();
...
anObj->SetLocalTransformation (theTrsf * anOldTrsf);
...
}``````
Here, if you need to have this transformation in TopoDS_Shape, use setting location of it.

Sample, how the manipulator works, you may found in DRAW of OCCT, or in repository ‘https://gitlab.com/ssv/lessons/-/tree/viewerManipulator’. It’s discussed in ‘http://analysissitus.org/forum/index.php?threads/youtube-lessons.3/page-2#post-1201’.

Concerning preparing TopLoc_Location, we usually do not make it by ourselves manually. It is generated by using some of OCCT methods inside. You may think about this class like as a chain of gp_Trsf, you understand it correctly. Here, if you need not the history of the transformations (by some custom reasons), you may prepare only one gp_Trsf and give it to TopoDS_Shape.

Best regards