![]() |
![]() |
Geoc (geocanvas) Reference Manual | ![]() |
---|
In order to display anything to a computer screen, device level coordinates
(pixels) are required at the lowest level. The CrCanvas
adds a level of abstraction by allowing the user to specify user coordinates.
The difference between user and device coordinates using the
CrCanvas
are defined by one or more levels of
cairo_matrix_t affine transformations. However, affine transformations alone
are not enough to determine pixel device locations as referenced to a
geographic projection.
The GeocProjection object solves this
problem by adding an additional level of abstraction between user coordinates
and geographic coordinates. The GeocProjection
acts as a
manager for one or more GeocCanvas objects.
It is the place to go to convert between user coordinates and geographic
coordinates. Projection properties that can be changed are projection string,
e.g. mercator, orthogonal, etc., the rotation, or the reference point.
An typical use of GeocProjection is to convert cursor position to longitude and latitude:
double ux, uy, lon, lat; ux = event->motion.x; uy = event->motion.y; /* Using the inverse of the current transformation matrix (CTM) will * convert from device to user coordinates. */ cairo_matrix_transform_point(inverse_matrix, &ux, &uy); /* This part converts from user coordinates to geographic coordinates. * It is not possible to convert directly between device and geographic * coordinates.*/ geo_projection_w2g(projection, ux, uy, &lon, &lat);
The GeocCanvas is derived from the
CrCanvas
. It adds geographically referenced viewport and
scroll region management to the canvas. The additional management is necessary
to allow the canvas to dynamically scale between a view that represents the
whole Earth and a view that represents less than a square mile in area. For a
case where you are looking at Tokyo, you would not expect to be able to scroll
to New York. Another benefit to managing the viewport area is in performance.
By connecting to the #viewport-changed signal, it is possible to swap in and out
high resolution maps.
Creating the canvas is essentially the same as creating a
CrCanvas
.
GtkWidget *canvas, *scrolledwindow; scrolledwindow = gtk_scrolled_window_new (NULL, NULL); canvas = GTK_WIDGET(g_object_new(GEOC_TYPE_CANVAS, NULL)); gtk_widget_show (canvas); gtk_container_add (GTK_CONTAINER (scrolledwindow), canvas);
The GeocItem stock object provides most of what
is necessary to simplify handling of the additional details imposed by the GeocProjection. The idea behind this is
that everything you would want to plot is either a line or a place. The GeocLines class is a
GeocItem
of either poly-lines or polygons that all share
the same properties. You might want to draw all Earth land mass as green
polygons. This can be accomplished using a single GeocLines object. If you
decide you want to draw each country in a separate color, then you can add
properties to each #CrLine canvas item as the data is built using the GeocItem
interface routines #geoc_item_begin, #geoc_item_add_point,
#geoc_item_end_segment, and #geoc_item_end. The GeocPlaces object uses the same interface,
but is designed for representing a data set where each element maps to a single
point in space. The GeocShapes does not use
this interface. It can be used to draw less homogenous groupings of primitive
shapes and lines. All Geoc.. canvas items assure that the geographic references
are maintained on the canvas without requiring an explicit connection to
GeocProjection
.
Here is an example of how to use the GeocItem
interface to draw a rectangle onto the canvas:
GeocItem *group; group = geoc_item_new(parent, GEOC_TYPE_LINES, "itemtype", CR_TYPE_LINE, "fill_color", "red", NULL); geoc_item_begin(group); geoc_item_add_point(group, -71.5, 41.0); geoc_item_add_point(group, -71.0, 41.0); geoc_item_add_point(group, -71.0, 40.5); geoc_item_add_point(group, -71.5, 40.5); geoc_item_end_segment(group); geoc_item_end(group);
This example draws a set of polygons defined in the "land.txt" file:
GeocCanvas *canvas; char data[80]; double lon, lat; /* The GeocCanvas will create its own projection if one is not specified. */ canvas = GEO_CANVAS(g_object_new (GEO_TYPE_CANVAS, NULL)); /* Using the #geoc_item_new constructor vice g_object_new, will cause the the * GeocItem to be parented and unreferenced in one step. */ item = geoc_item_new(GEOC_ITEM(CR_CANVAS(canvas)->root), /* This tells the constructor what derived object */ GEOC_TYPE_LINES, "fill-color", "green", NULL); geoc_item_begin(item); while (fgets(data, 80, fd)) { if (sscanf(data, "%f %f", &lon, &lat) == 2) geoc_item_add_point(item, lon, lat, NULL); else geoc_item_end_segment(item, NULL); } geoc_item_end(item); /* That's it.*/