# ClanLib Tips & Tricks

 ``` HOME ¦ MATH ¦ NETWORK ```

ClanLib Home

## Rotating objects »

Sometimes you need to rotate not only an image, but also the images location. Then the rotate() method of CL_Sprite and CL_Surface is not enough.

### Rotation math »

To rotate a point around (0, 0), you'll need to apply the following transformation.

x' = x cosŲ - y sinŲ
y' = x sinŲ + y cosŲ

Simple rotation
```    float new_x = old_x * ::cos(fi_rad) - old_y * ::sin(fi_rad);

To rotate around an arbitrary point in the plane, the point needs first be translated to (0, 0), rotated, and finally translated back to the original position.

Rotation around arbitrary point
```    CL_Pointf the_point(230.f, 480.f);

// The point to rotate around
CL_Pointf rotate_around_me(230.f, 480.f);

float rotation_angle_degrees = 45.f;

// The trigonometric functions needs radians
float rotation_angle_radians = rotation_angle_degrees * M_PI / 180;

CL_Pointf new_pos(the_point);

// Translate
new_pos -= rotate_around_me;

// Rotate
the_point.x = new_pos.x * ::cos(rotation_angle_radians) -
the_point.y = new_pos.x * ::sin(rotation_angle_radians) +

// Translate back
the_point += rotate_around_me;```

Now that we know how to do it we can optimise the code. There is no point in calculating the cosŲ and sinŲ twice for each calculation. The value should be cached. And what if we need to rotate multiple points at the same time?

### Final solution »

rotation2dcalculator.h
```class Rotation2DCalculator
{
public:
Rotation2DCalculator(const CL_Pointf& rotation_hotspot, float angle_deg)
: hotspot(rotation_hotspot), angle(angle_deg)
{
// cache sin and cos calcs
float angle_rad = angle_deg * M_PI / 180;
}

inline void rotate(CL_Pointf &p) const;

protected:
CL_Pointf hotspot;
float angle, sin_fi, cos_fi;
};

inline void Rotation2DCalculator::rotate(CL_Pointf &p) const
{
CL_Pointf new_pos(p);

// Translate
new_pos -= hotspot;

// Rotate
p.x = new_pos.x * cos_fi - new_pos.y * sin_fi;
p.y = new_pos.x * sin_fi + new_pos.y * cos_fi;

// Translate back
p += hotspot;
}```

Now it's possible to use a Rotation2DCalculator object for multiple transformations. Supplying getters and setters for the rotation hotspot and the rotation angle will complete the class.

Note: This functionality can also be acheived using CL_Vector::rotate(). But if speed is an issue, this here idea is the way to go. It can be extended to three dimensions for those in need.

Back