html 5 canvas coordinates, jQuery and animating graphs - Part 7 in a series

Centering and scaling my graph

By trial and error I lined up the origin of my graph, and get the aspect ratio correct, as this graph of x-squared from -1 to 1 illustrates
By trial and error I lined up the origin of my graph, and get the aspect ratio correct, as this graph of x-squared from -1 to 1 illustrates
However, the control points of my Bezier Curves were not aligning with the curves drawn; time to solve the problem systematically
However, the control points of my Bezier Curves were not aligning with the curves drawn; time to solve the problem systematically

reviewing linear algebra so I can control canvas

Even if the specifics of my application is not of interest to you, if you want to implement applications that interact with the user, and use HTML 5's canvas tag, you will need to find a way to deal with the issues discussed in this Hub.

In my last Hub on applying canvas to my graphing calculator and Bezier curve design application, I left some open questions about the mapping of my coordinates to canvas coordinates. In this Hub, I will explain canvas's coordinate transformation facilities.
In order to explain canvas's coordinate system, I have to first review a little linear algebra. The matrix equation below expresses a transform canvas applies to coordinates.


a c e x
b d f * y
0 0 1 1


You may or may not recall that when multiplying matrices, you multiply each element of a row with each element of a column and add all of the results to form an element of the resulting matrix. The matrix equation above is a short-hand method of writing:


x = a*x + b*y + e*1
y= c*x + d*y + f*1
z= 0*x+ 0*y + 1*1


In two dimensions this is a convenient notation for expressing scaling and rotation. Scaling with fixed aspect ratio would be expressed as a matrix


s 0
0 s


where s is the scaling factor.
A rotation would be expressed as a matrix of the form


cos(r) -sin(r)
sin(r) cos(r)


Where r is the angle of the rotation in radians.
This notation can be extened to express translations in space by adding a third collumn and a third row of the matrix


a c e
b d f
0 0 1


Where e is the translation in the x direction and f is the translation in the y direction. Points are denoted:


x
y
1


To make the matrix multiplication work out.


If you wish to combine a series of scalings, rotations and translations, you would multiply the coresponding matrixes. The first transformation to apply would be the leftmost matrix, and so on. The matrix resulting from the matrix multiplication would represent all of the scalings, rotations and translations that were to be applied.


What I have just described is the model of coordinate transformation that canvas supports. Canvas has a number of methods that allow the programmer to manipulate this model ( scale, rotate, transform, setTransform ). Each time one of these functions is called, it essentially multiplies another matrix with the previous transformation matrix.


The canvas coordinate system uses increasing x values to the right and increasing y values down. The origin is the upper left hand corner.


Now, it is time to use this knowledge to solve my problem systematically. The remaining difficulty I have is that there is no way to get canvas to report its mapping of a point to absolute screen coordinates. So, I will create a visual aid to get this information. I wrote a function to draw hash marks along the top edge, left edge and center axis of the canvas object, calibrateCanvas. Its "coord" argument is a description of the mapping between my application's coordinates and absolute screen coordinates, that I have discussed in previous Hubs. The "argument" is a canvas context object.

As the pictures illustrate, I was able to use this calibration output to find an appropriate translation and scaling. The translation just requires subtracting the canvas tags position from the absolute position of graphic elements that are to be rendered by canvas. This is expected and makes sense.

I was not expecting that I would also have to scale my images, but it is quite evident that I do. For this, I applied different scale factors to x and y until the center of the graphing area lined up with the hash marks, calibrateCanvas generated.

I don't know if browsers other than Firefox use a different scale for canvas objects, if it is some fluke of my computer's setup that any scaling is necessary, or if the translation and scale operations I found are broadly applicable. If it is something that varies from system to system, it would be best to give the user an interface where the user could make the adjustments themselves, but I will leave how to do that as an exercise for the reader.


code to draw a coordinate grid in canvas

function calibrateCanvas ( coord, ctx )
{
	var i;
	var maxx;
	var minx;
	var maxy;
	var miny;

	if( coord.screenx0 > coord.screenx1 ) {
		maxx = coord.screenx0;
		minx = coord.screenx1;
	} else {
		maxx = coord.screenx1;
		minx = coord.screenx0;
	}
	if( coord.screeny0 > coord.screeny1 ) {
		maxy = coord.screeny0;
		miny = coord.screeny1;
	} else {
		maxy = coord.screeny1;
		miny = coord.screeny0;
	}

	for( i = 0 ; i < maxx ; i += 10 ) {
		ctx.fillRect(minx + i,miny + Math.round((maxy-miny)/2),1,5 );
		ctx.fillRect(minx + i,miny,1,5 );
	}
	for( i = 0 ; i < maxy ; i += 10 ) {
		ctx.fillRect(minx + Math.round((maxx-minx)/2),miny + i,5,1 );
		ctx.fillRect(minx,miny + i,5,1 );
	}
}

using calibration marks to determine screen point mappings

With no transformations applied the canvas image is larger and shifted from where it should be.
With no transformations applied the canvas image is larger and shifted from where it should be.
shifting by -left, -top, gets the upper corner of my graph into the right location
shifting by -left, -top, gets the upper corner of my graph into the right location
scaling x by .3 and y by .6, after translation fixes the size problem
scaling x by .3 and y by .6, after translation fixes the size problem
Now, my Bezier  Curve control points match up with the graphs that are rendered.
Now, my Bezier Curve control points match up with the graphs that are rendered.

More by this Author


Comments

No comments yet.

    Sign in or sign up and post using a HubPages Network account.

    0 of 8192 characters used
    Post Comment

    No HTML is allowed in comments, but URLs will be hyperlinked. Comments are not for promoting your articles or other sites.


    Click to Rate This Article
    working