[cairo] Transformations usage
Daniele Dario
d.dario76 at gmail.com
Mon Dec 11 12:23:55 UTC 2017
Hi Bill,
thanks for the hints.
Spent some time to figure out how it works but finally I got something
working :-)
The first issue I had was that cairo_translate (cr, -X, -Y) seems
wrong: if I use X, Y I get it working properly.
Daniele.
On Wed, 2017-12-06 at 10:29 -0800, Bill Spitzak wrote:
> 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?
> >
> > Thanks in advance,
> > 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
More information about the cairo
mailing list