views:

67

answers:

2

I'm making a vector drawing application and noticed that Anti Grain Geometry have an example that does exactly what I want. http://www.antigrain.com/demo/index.html then below there is an example on perspective for Win32. I don't understand their cpp file. Based on this example. If I have a bunch of verticies to form an object, like their lion, and then I have 4 verticies as control points, how could I achieve their effect? Ex, what transformation do I apply to each point?

Thanks

+1  A: 

You're talking about perspective transformation from 2D planar onto a square 'in space' I think.

Well - This one is not that difficult. The mathematics are explained in the paper:

Heckbert, Paul, Fundamentals of Texture Mapping and Image Warping, Master’s thesis, UCB/CSD 89/516, CS Division, U.C. Berkeley, June 1989.

(I don't link to the paper due to copyright reasons. It's available on the net and you shouldn't have any problems finding it though)

This gives you the math and some ready to use equations to do it.

If you are looking for some "easy to rip" code I suggest to download the OpenVG reference implementation and take a close look at the functions "vguComputeWarpQuadToSquare", "vguComputeWarpSquareToQuad" and "vguComputeWarpQuadToQuad" :-) They cover all you need.

Download here: http://www.khronos.org/registry/vg/ri/openvg-1.1-ri.zip

These functions will calculate a 3x3 matrix that does the transformation. To use this matrix you have to extend your 2D coordinates into 2D homogenous coordinates. That's not that difficult but beyond the scope of the question. If you need help to work with them I suggest that you ask that in a different question.

Nils Pipenbrinck
+1  A: 

From that very page you posted, there's a link to the source code. I'll explain the bilinear transformation in

http://www.antigrain.com/__code/include/agg_trans_bilinear.h.html

The idea here is to find a transformation of the form:

output_x = a * input_x + b * input_x * input_y + c * input_y + d
output_y = e * input_x + f * input_x * input_y + g * input_y + h

The term "bilinear" comes from each of those equations being linear in either of the input coordinates by themselves. We want to solve for the right values of a, b, c, and d. Say you have the reference rectangle r1, r2, r3, r4 which you want to map to (0,0), (1,0), (0,1), (1,1) (or some image coordinate system).

For a,b,c,d:

0 = a * r1_x + b * r1_x * r1_y + c * r1_y + d
1 = a * r2_x + b * r2_x * r2_y + c * r2_y + d
0 = a * r3_x + b * r3_x * r3_y + c * r3_y + d
1 = a * r4_x + b * r4_x * r4_y + c * r4_y + d

For e,f,g,h:

0 = e * r1_x + f * r1_x * r1_y + g * r1_y + h
0 = e * r2_x + f * r2_x * r2_y + g * r2_y + h
1 = e * r3_x + f * r3_x * r3_y + g * r3_y + h
1 = e * r4_x + f * r4_x * r4_y + g * r4_y + h

You can solve this however you like best. (If you're familiar with matrix notation, these are two matrix equations for which the matrix is the same, and then you simply need to find the LU decomposition once, and solve the two unknown vectors). The coefficients are then applied to map the interior of the rectangle to the position in the rectangle.

If by any chance you're looking for the inverse transform, that is, if you want to know where a given pixel will land, you simply switch inputs and outputs:

For a,b,c,d:

r1_x = a * 0 + b * 0 * 0 + c * 0 + d
r2_x = a * 1 + b * 1 * 0 + c * 0 + d
r3_x = a * 0 + b * 0 * 1 + c * 1 + d
r4_x = a * 1 + b * 1 * 1 + c * 1 + d

For e,f,g,h:

r1_y = e * 0 + f * 0 * 0 + g * 0 + h
r2_y = e * 1 + f * 1 * 0 + g * 0 + h
r3_y = e * 0 + f * 0 * 1 + g * 1 + h
r4_y = e * 0 + f * 0 * 1 + g * 1 + h
Carlos Scheidegger