# [cairo] Transformations usage

Bill Spitzak spitzak at gmail.com
Wed Dec 6 18:29:33 UTC 2017

```It is  probably easier to use a series of cairo transforms. But I
think the main problem is that the y in the matrix needs to be
height-offset.

If you have a point XY in your map that you want to be in the center
of the window, I would do this:

cairo_translate(cr, -X, -Y); // put center at 0,0
cairo_scale(cr, 1, -1); // flip from y-up to y-down
cairo_rotate(cr, r); // rotate ccw by r degrees
cairo_scale(cr, s, s); // scale where s is pixels/meter
cairo_translate(cr, w/2, h/2); // move center back to center of
window of size w×h

On Wed, Dec 6, 2017 at 2:46 AM, Daniele Dario <d.dario76 at gmail.com> wrote:
> Hello everyone,
> I'm trying to create my own widget on GTK+ to display a clip of a 2D
> map where I placed some polygons. The point of view can be moved inside
> the map and may rotate.
>
> The main idea is that I draw the map on a cairo_surface_t once and than
> on expose event I use coordinates of POV to center the device surface
> to paint on the map, rotate the map, scale, clip and paint.
>
> To start I tried to use a transformation matrix to be able to draw
> using native coordinates on a surface but I'm getting confused on how
> transformation affects drawing.
>
> At the end of the code below I expect to have a map painted on the
> surface. In order to paint it on the widget I'd need another
> transformation because:
> - map size in the example is 165x165 and scale is 1 pixel = 1 [m]
> - widget will have a different ratio
>
> Can someone point me out on some examples or with some hint on how to
> achieve what I'm looking for?
>
> Daniele.
>
> /*
>  * Create a surface for the map:
>  *  - 1 pixel = 1 [m]
>  *  - assume map width >= height
>  *  - coordinates of polygons are relative to an
>  *    arbitrary origin placed at
>  *    O = (x = height/2, y = height/2)
>  */
> gint site_width = 165;
> gint site_height = 165;
> cairo_surface_t *map = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
>         site_width, site_height);
>
> /* Origin coordinates are relative */
> gdouble offset = site_height / 2.;
>
> /* Create a context to draw on the surface */
> cr = cairo_create (map);
>
> /*
>  * FIXME: Need a transformation in order to use
>  * coordinates relative to O:
>  *  - x axis is correct just needs translation of offset
>  *  - y axis is inverse and needs translation of offset
>  */
> cairo_matrix_t mat;
> cairo_matrix_init (&mat, 1.0, 0.0, 0.0, -1.0, offset, offset);
> cairo_transform (cr, &mat);
>
> /* TODO: draw all objects on the map */
> /* Array of (x,y) coordinates to represent a polygon */
> GtkScuiPoint v1 [4] = {
>         { -20., -40.},
>         { -20.,   0.},
>         { -50.,   0.},
>         { -50., -40.}
> };
>
> //cairo_set_line_width (cr, 0.1);
>
> cairo_set_source_rgba (cr, 1., 0., 0., .7);
>
> /* Wrapper to draw and fill polygon  */
> scui_cairo_draw_polygon (cr, TRUE, v1, 4);
>
> GtkScuiPoint v2 [4] = {
>         { 40.,  0.},
>         { 40., 20.},
>         { 20., 20.},
>         { 20.,  0.}
> };
>
> cairo_set_source_rgba (cr, 0., 0., 1., .7);
>
> /* Wrapper to draw an empty polygon  */
> scui_cairo_draw_polygon (cr, FALSE, v2, 4);
>
> /* TODO: Store surface to avoid re-painting it */
>
> /* Destroy context */
> cairo_destroy (cr);
>
>
> --
> cairo mailing list
> cairo at cairographics.org
> https://lists.cairographics.org/mailman/listinfo/cairo
```