I wanna make program on Bézier surfaces, I found on internet this article, there is one approach how to do It, but I don't understand second step definitely and third step particularly. Or may be I just cant imagine what author can mean by that.
B. Use blending tables to calculate points in "row curve":
for( u = 0; u < 10; u++ )
{
blend row 0 control points -> new control point
blend row 1 control points -> new control point
blend row 2 control points -> new control point
blend row 3 control points -> new control point
for( v = 0; v < 10; v++ )
{
blend 4 new control points -> point on surface
}
}
C. Generate edges and polygons from grid of surface points.
Can anyone explain what I could mean? Thx.
A Bezier-surface is a bezier-curve, where the control-points are moving along other Bezier-curves, instead of being stationary.
B(0,u) = (1-u)^3
B(1,u) = 3*u*(1-u)^2
B(2,u) = 3*u^2*(1-u)
B(3,u) = u^3
C[0..3, 0..3] = control points
Curve(t,C0,C1,C2,C3) = B(0,t)*C0 + B(1,t)*C1 + B(2,t)*C2 + B(3,t)*C3
Surface(s,t,C[0..3,0..3]) =
Curve(t, Curve(s, C[0,0], C[1,0], C[2,0], C[3,0]),
Curve(s, C[0,1], C[1,1], C[2,1], C[3,1]),
Curve(s, C[0,2], C[1,2], C[2,2], C[3,2]),
Curve(s, C[0,3], C[1,3], C[2,3], C[3,3]))
These functions samples the curve (or surface) for specific values of t (and s).
The article talks about caching the values of the Bernstain polynomials (the B(i,u) function) before calculating the sums. This is so you don't have to recalculate it each time.
It then goes on talking about subdivision. This involves breaking the four control points in each curve into two groups of four. Each group will trace half the original curve.
Advancing this into surfaces, you break each row-curve into two, and then each column-curve into two. This will give you four surfaces tracing part of the original curve.
Subdivision is generally quicker than sampling the curve/surface.
SplitCurve(C0,C1,C2,C3) = [
C0, # First control-point of first sub-curve
(C0 + C1)/2, # Second control-point of first sub-curve
(C0 + 2*C1 + C2)/4, # Third control-point of first sub-curve
(C0 + 3*C1 + 3*C2 + C3)/8, # Shared first/last control-point
(C1 + 2*C2 + C3)/4, # Second control-point of second sub-curve
(C2 + C3)/2, # Third control-point of second sub-curve
C3 # Fourth control-point of second sub-curve
]
SplitSurface(C[0..3,0..3]) =
col0 = SplitCurve(C[0,0], C[0,1], C[0,2], C[0,3])
col1 = SplitCurve(C[0,0], C[0,1], C[0,2], C[0,3])
col2 = SplitCurve(C[0,0], C[0,1], C[0,2], C[0,3])
col3 = SplitCurve(C[0,0], C[0,1], C[0,2], C[0,3])
return [
SplitCurve(col0[0], col1[0], col2[0], col3[0]),
SplitCurve(col0[1], col1[1], col2[1], col3[1]),
SplitCurve(col0[2], col1[2], col2[2], col3[2]),
SplitCurve(col0[3], col1[3], col2[3], col3[3]),
SplitCurve(col0[4], col1[4], col2[4], col3[4]),
SplitCurve(col0[5], col1[5], col2[5], col3[5]),
SplitCurve(col0[6], col1[6], col2[6], col3[6])
]
Continue to subdivide each sub-surface, until all control points lies within the same pixel. Here "pixel" refers to the projected curve. To check this, the naïve way would be to project each control point to screen coordinates.
To create triangle-meshes, you can subdivide the control-points some fixed number of times, then pick the top-left control point of each surface.
Related
I have the x, y co-ordinates of a point on a rotated image by certain angle. I want to find the co-ordinates of the same point in the original, non-rotated image.
Please check the first image which is simpler:
UPDATED image, SIMPLIFIED:
OLD image:
Let's say the first point is A, the second is B and the last is C. I assume you have the rotation matrice R (see Wikipedia Rotation Matrix if not) et the translation vector t, so that B = R*A and C = B+t.
It comes C = R*A + t, and so A = R^1*(C-t).
Edit: If you only need the non rotated new point, simply do D = R^-1*C.
First thing to do is defining the reference system (how "where the points lies with respect to each image" will be translated into numbers). I guess that you want to rely on a basic 2D reference system, given by a single point (a couple of X/Y values). For example: left/lower corner (min. X and min. Y).
The algorithm is pretty straightforward:
Getting the new defining reference point associated with the
rotated shape (min. X and min. Y), that is, determining RefX_new and
RefY_new.
Applying a basic conversion between reference systems:
X_old = X_new + (RefX_new - RefX_old)
Y_old = Y_new + (RefY_new -
RefY_old)
----------------- UPDATE TO RELATE FORMULAE TO NEW CAR PIC
RefX_old = min X value of the CarFrame before being rotated.
RefY_old = max Y value of the CarFrame before being rotated.
RefX_new = min X value of the CarFrame after being rotated.
RefY_new = max Y value of the CarFrame after being rotated.
X_new = X of the point with respect to the CarFrame after being rotated. For example: if RefX_new = 5 with respect to absolute frame (0,0) and X of the point with respect to this absolute frame is 8, X_new would be 3.
Y_new = Y of the point with respect to CarFrame after being rotated (equivalently to point above)
X_old_C = X_new_C(respect to CarFrame) + (RefX_new(CarFrame_C) - RefX_old(CarFrame_A))
Y_old_C = Y_new_C(respect to CarFrame) + (RefY_new(CarFrame_C) - RefY_old(CarFrame_A))
These coordinates are respect to the CarFrame and thus you might have to update them with respect to the absolute frame (0,0, I guess), as explained above, that is:
X_old_D_absolute_frame = X_old_C + (RefX_new(CarFrame_C) + RefX_global(i.e., 0))
Y_old_D_absolute_frame = Y_old_C + (RefY_new(CarFrame_C) + RefY_global(i.e., 0))
(Although you should do that once the CarFrame is in its "definitive position" with respect to the global frame, that is, on picture D (the point has the same coordinates with respect to the CarFrame in both picture C and D, but different ones with respect to the global frame).)
It might seem a bit complex put in this way; but it is really simple. You have just to think carefully about one case and create the algorithm performing all the actions. The idea is extremely simple: if I am on 8 inside something which starts in 5; I am on 3 with respect to the container.
------------ UPDATE IN THE METHODOLOGY
As said in the comment, these last pictures prove that the originally-proposed calculation of reference (max. Y/min. X) is not right: it shouldn't be the max./min. values of the carFrame but the minimum distances to the closer sides (= perpendicular line from the left/bottom side to the point).
------------ TRIGONOMETRIC CALCS FOR THE SPECIFIC EXAMPLE
The algorithm proposed is the one you should apply in any situation. Although in this specific case, the most difficult part is not moving from one reference system to the other, but defining the reference point in the rotated system. Once this is done, the application to the non-rotated case is immediate.
Here you have some calcs to perform this action (I have done it pretty quickly, thus better take it as an orientation and do it by your own); also I have only considered the case in the pictures, that is, rotation over the left/bottom point:
X_rotated = dx * Cos(alpha)
where dx = X_orig - (max_Y_CarFrame - Y_Orig) * Tan(alpha)
Y_rotated = dy * Cos(alpha)
where dy = Y_orig - X_orig * Tan(alpha)
NOTE: (max_Y_CarFrame - Y_Orig) in dx and X_orig in dy expect that the basic reference system is 0,0 (min. X and min. Y). If this is not the case, you would have to change this variables.
The X_rotated and Y_rotated give the perpendicular distance from the point to the closest side of the carFrame (respectively, left and bottom side). By applying these formulae (I insist: analyse them carefully), you get the X_old_D_absolute_frame/Y_old_D_absolute_frame that is, you have just to add the lef/bottom values from the carFrame (if it is located in 0,0, these would be the final values).
I have an array of points (x0,y0)... (xn,yn) monotonic in x and wish to draw the "best" curve through these using Bezier curves. This curve should not be too "jaggy" (e.g. similar to joining the dots) and not too sinuous (and definitely not "go backwards"). I have created a prototype but wonder whether there is an objectively "best solution".
I need to find control points for all segments xi,y1 x(i+1)y(i+1). My current approach (except for the endpoints) for a segment x(i), x(i+1) is:
find the vector x(i-1)...x(i+1) , normalize, and scale it by factor * len(i,i+1) to give the vector for the leading control point
find the vector x(i+2)...x(i) , normalize, and scale it by factor * len(i,i+1) to give the vector for the trailing control point.
I have tried factor=0.1 (too jaggy), 0.33 (too curvy) and 0.20 - about right. But is there a better approach which (say) makes 2nd and 3nd derivatives as smooth as possible. (I assume such an algorithm is implemented in graphics packages)?
I can post pseudo/code if requested. Here are the three images (0.1/0.2/0.33). The control points are shown by straight lines: black (trailing) and red (leading)
Here's the current code. It's aimed at plotting Y against X (monotonic X) without close-ing. I have built my own library for creating SVG (preferred output); this code creates triples of x,y in coordArray for each curve segment (control1, xcontrol2, end). Start is assumed by last operation (Move or Curve). It's Java but should be easy to interpret (CurvePrimitive maps to cubic, "d" is the String representation of the complete path in SVG).
List<SVGPathPrimitive> primitiveList = new ArrayList<SVGPathPrimitive>();
primitiveList.add(new MovePrimitive(real2Array.get(0)));
for(int i = 0; i < real2Array.size()-1; i++) {
// create path 12
Real2 p0 = (i == 0) ? null : real2Array.get(i-1);
Real2 p1 = real2Array.get(i);
Real2 p2 = real2Array.get(i+1);
Real2 p3 = (i == real2Array.size()-2) ? null : real2Array.get(i+2);
Real2Array coordArray = plotSegment(factor, p0, p1, p2, p3);
SVGPathPrimitive primitive = new CurvePrimitive(coordArray);
primitiveList.add(primitive);
}
String d = SVGPath.constructDString(primitiveList);
SVGPath path1 = new SVGPath(d);
svg.appendChild(path1);
/**
*
* #param factor to scale control points by
* #param p0 previous point (null at start)
* #param p1 start of segment
* #param p2 end of segment
* #param p3 following point (null at end)
* #return
*/
private Real2Array plotSegment(double factor, Real2 p0, Real2 p1, Real2 p2, Real2 p3) {
// create p1-p2 curve
double len12 = p1.getDistance(p2) * factor;
Vector2 vStart = (p0 == null) ? new Vector2(p2.subtract(p1)) : new Vector2(p2.subtract(p0));
vStart = new Vector2(vStart.getUnitVector().multiplyBy(len12));
Vector2 vEnd = (p3 == null) ? new Vector2(p2.subtract(p1)) : new Vector2(p3.subtract(p1));
vEnd = new Vector2(vEnd.getUnitVector().multiplyBy(len12));
Real2Array coordArray = new Real2Array();
Real2 controlStart = p1.plus(vStart);
coordArray.add(controlStart);
Real2 controlEnd = p2.subtract(vEnd);
coordArray.add(controlEnd);
coordArray.add(p2);
// plot controls
SVGLine line12 = new SVGLine(p1, controlStart);
line12.setStroke("red");
svg.appendChild(line12);
SVGLine line21 = new SVGLine(p2, controlEnd);
svg.appendChild(line21);
return coordArray;
}
A Bezier curve requires the data points, along with the slope and curvature at each point. In a graphics program, the slope is set by the slope of the control-line, and the curvature is visualized by the length.
When you don't have such control-lines input by the user, you need to estimate the gradient and curvature at each point. The wikipedia page http://en.wikipedia.org/wiki/Cubic_Hermite_spline, and in particular the 'interpolating a data set' section has a formula that takes these values directly.
Typically, estimating these values from points is done using a finite difference - so you use the values of the points on either side to help estimate. The only choice here is how to deal with the end points where there is only one adjacent point: you can set the curvature to zero, or if the curve is periodic you can 'wrap around' and use the value of the last point.
The wikipedia page I referenced also has other schemes, but most others introduce some other 'free parameter' that you will need to find a way of setting, so in the absence of more information to help you decide how to set other parameters, I'd go for the simple scheme and see if you like the results.
Let me know if the wikipedia article is not clear enough, and I'll knock up some code.
One other point to be aware of: what 'sort' of Bezier interpolation are you after? Most graphics programs do cubic bezier in 2 dimensions (ie you can draw a circle-like curve), but your sample images look like it could be 1d functions approximation (as in for every x there is only one y value). The graphics program type curve is not really mentioned on the page I referenced. The maths involved for converting estimate of slope and curvature into a control vector of the form illustrated on http://en.wikipedia.org/wiki/B%C3%A9zier_curve (Cubic Bezier) would take some working out, but the idea is similar.
Below is a picture and algorithm for a possible scheme, assuming your only input is the three points P1, P2, P3
Construct a line (C1,P1,C2) such that the angles (P3,P1,C1) and (P2,P1,C2) are equal. In a similar fashion construct the other dark-grey lines. The intersections of these dark-grey lines (marked C1, C2 and C3) become the control-points as in the same sense as the images on the Bezier Curve wikipedia site. So each red curve, such as (P3,P1), is a quadratic bezier curve defined by the points (P3, C1, P1). The construction of the red curve is the same as given on the wikipedia site.
However, I notice that the control-vector on the Bezier Curve wikipedia page doesn't seem to match the sort of control vector you are using, so you might have to figure out how to equate the two approaches.
I tried this with quadratic splines instead of cubic ones which simplifies the selection of control points (you just choose the gradient at each point to be a weighted average of the mean gradients of the neighbouring intervals, and then draw tangents to the curve at the data points and stick the control points where those tangents intersect), but I couldn't find a sensible policy for setting the gradients of the end points. So I opted for Lagrange fitting instead:
function lagrange(points) { //points is [ [x1,y1], [x2,y2], ... ]
// See: http://www.codecogs.com/library/maths/approximation/interpolation/lagrange.php
var j,n = points.length;
var p = [];
for (j=0;j<n;j++) {
p[j] = function (x,j) { //have to pass j cos JS is lame at currying
var k, res = 1;
for (k=0;k<n;k++)
res*=( k==j ? points[j][1] : ((x-points[k][0])/(points[j][0]-points[k][0])) );
return res;
}
}
return function(x) {
var i, res = 0;
for (i=0;i<n;i++)
res += p[i](x,i);
return res;
}
}
With that, I just make lots of samples and join them with straight lines.
This is still wrong if your data (like mine) consists of real world measurements. These are subject to random errors and if you use a technique that forces the curve to hit them all precisely, then you can get silly valleys and hills between the points. In cases like these, you should ask yourself what order of polynomial the data should fit and ... well ... that's what I'm about to go figure out.
I've got a shape consisting of four points, A, B, C and D, of which the only their position is known. The goal is to transform these points to have specific angles and offsets relative to each other.
For example: A(-1,-1) B(2,-1) C(1,1) D(-2,1), which should be transformed to a perfect square (all angles 90) with offsets between AB, BC, CD and AD all being 2. The result should be a square slightly rotated counter-clockwise.
What would be the most efficient way to do this?
I'm using this for a simple block simulation program.
As Mark alluded, we can use constrained optimization to find the side 2 square that minimizes the square of the distance to the corners of the original.
We need to minimize f = (a-A)^2 + (b-B)^2 + (c-C)^2 + (d-D)^2 (where the square is actually a dot product of the vector argument with itself) subject to some constraints.
Following the method of Lagrange multipliers, I chose the following distance constraints:
g1 = (a-b)^2 - 4
g2 = (c-b)^2 - 4
g3 = (d-c)^2 - 4
and the following angle constraints:
g4 = (b-a).(c-b)
g5 = (c-b).(d-c)
A quick napkin sketch should convince you that these constraints are sufficient.
We then want to minimize f subject to the g's all being zero.
The Lagrange function is:
L = f + Sum(i = 1 to 5, li gi)
where the lis are the Lagrange multipliers.
The gradient is non-linear, so we have to take a hessian and use multivariate Newton's method to iterate to a solution.
Here's the solution I got (red) for the data given (black):
This took 5 iterations, after which the L2 norm of the step was 6.5106e-9.
While Codie CodeMonkey's solution is a perfectly valid one (and a great use case for the Lagrangian Multipliers at that), I believe that it's worth mentioning that if the side length is not given this particular problem actually has a closed form solution.
We would like to minimise the distance between the corners of our fitted square and the ones of the given quadrilateral. This is equivalent to minimising the cost function:
f(x1,...,y4) = (x1-ax)^2+(y1-ay)^2 + (x2-bx)^2+(y2-by)^2 +
(x3-cx)^2+(y3-cy)^2 + (x4-dx)^2+(y4-dy)^2
Where Pi = (xi,yi) are the corners of the fitted square and A = (ax,ay) through D = (dx,dy) represent the given corners of the quadrilateral in clockwise order. Since we are fitting a square we have certain contraints regarding the positions of the four corners. Actually, if two opposite corners are given, they are enough to describe a unique square (save for the mirror image on the diagonal).
Parametrization of the points
This means that two opposite corners are enough to represent our target square. We can parametrise the two remaining corners using the components of the first two. In the above example we express P2 and P4 in terms of P1 = (x1,y1) and P3 = (x3,y3). If you need a visualisation of the geometrical intuition behind the parametrisation of a square you can play with the interactive version.
P2 = (x2,y2) = ( (x1+x3-y3+y1)/2 , (y1+y3-x1+x3)/2 )
P4 = (x4,y4) = ( (x1+x3+y3-y1)/2 , (y1+y3+x1-x3)/2 )
Substituting for x2,x4,y2,y4 means that f(x1,...,y4) can be rewritten to:
f(x1,x3,y1,y3) = (x1-ax)^2+(y1-ay)^2 + ((x1+x3-y3+y1)/2-bx)^2+((y1+y3-x1+x3)/2-by)^2 +
(x3-cx)^2+(y3-cy)^2 + ((x1+x3+y3-y1)/2-dx)^2+((y1+y3+x1-x3)/2-dy)^2
a function which only depends on x1,x3,y1,y3. To find the minimum of the resulting function we then set the partial derivatives of f(x1,x3,y1,y3) equal to zero. They are the following:
df/dx1 = 4x1-dy-dx+by-bx-2ax = 0 --> x1 = ( dy+dx-by+bx+2ax)/4
df/dx3 = 4x3+dy-dx-by-bx-2cx = 0 --> x3 = (-dy+dx+by+bx+2cx)/4
df/dy1 = 4y1-dy+dx-by-bx-2ay = 0 --> y1 = ( dy-dx+by+bx+2ay)/4
df/dy3 = 4y3-dy-dx-2cy-by+bx = 0 --> y3 = ( dy+dx+by-bx+2cy)/4
You may see where this is going, as simple rearrangment of the terms leads to the final solution.
Final solution
I have read similar topics in order to find solution, but with no success.
What I'm trying to do is make the tool same as can be found in CorelDraw, named "Pen Tool". I did it by connecting Bezier cubic curves, but still missing one feature, which is dragging curve (not control point) in order to edit its shape.
I can successfully determine the "t" parameter on the curve where dragging should begin, but don't know how to recalculate control points of that curve.
Here I want to higlight some things related to CorelDraw''s PenTool behaviour that may be used as constaints. I've noticed that when dragging curve strictly vertically, or horizontally, control points of that Bezier curve behave accordingly, i.e. they move on their verticals, or horizontals, respectively.
So, how can I recalculate positions of control points while curve dragging?
Ive just look into Inkspace sources and found such code, may be it help you:
// Magic Bezier Drag Equations follow!
// "weight" describes how the influence of the drag should be distributed
// among the handles; 0 = front handle only, 1 = back handle only.
double weight, t = _t;
if (t <= 1.0 / 6.0) weight = 0;
else if (t <= 0.5) weight = (pow((6 * t - 1) / 2.0, 3)) / 2;
else if (t <= 5.0 / 6.0) weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5;
else weight = 1;
Geom::Point delta = new_pos - position();
Geom::Point offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta;
Geom::Point offset1 = (weight/(3*t*t*(1-t))) * delta;
first->front()->move(first->front()->position() + offset0);
second->back()->move(second->back()->position() + offset1);
In you case "first->front()" and "second->back()" would mean two control points
The bezier curve is nothing more then two polynomials: X(t), Y(t).
The cubic one:
x = ax*t^3 + bx*t^2 + cx*t + dx
0 <= t <= 1
y = ay*t^3 + by*t^2 + cy*t + dy
So if you have a curve - you have the poly coefficients. If you move your point and you know it's t parameter - then you can simply recalculate the poly's coefficients - it will be a system of 6 linear equations for coefficients (for each of the point). The system is subdivided per two systems (x and y) and can be solved exactly or using some numerical methods - they are not hard too.
So your task now is to calculate control points of your curve when you know the explicit equation of your curve.
It can be also brought to the linear system. I don't know how to do it for generalized Bezier curve, but it is not hard for cubic or quadric curves.
The cubic curve via control points:
B(t) = (1-t)^3*P0 + 3(1-t)^2*t*P1 + 3(1-t)*t^2*P2 + t^3*P3
Everything you have to do is to produce the standard polynomial form (just open the brackets) and to equate the coefficients. That will provide the final system for control points!
When you clicks on curve, you already know position of current control point. So you can calculate offset X and offset Y from that point to mouse position. In case of mouse move, you would be able to recalculate new control point with help of X/Y offsets.
Sorry for my english
Given two image buffers (assume it's an array of ints of size width * height, with each element a color value), how can I map an area defined by a quadrilateral from one image buffer into the other (always square) image buffer? I'm led to understand this is called "projective transformation".
I'm also looking for a general (not language- or library-specific) way of doing this, such that it could be reasonably applied in any language without relying on "magic function X that does all the work for me".
An example: I've written a short program in Java using the Processing library (processing.org) that captures video from a camera. During an initial "calibrating" step, the captured video is output directly into a window. The user then clicks on four points to define an area of the video that will be transformed, then mapped into the square window during subsequent operation of the program. If the user were to click on the four points defining the corners of a door visible at an angle in the camera's output, then this transformation would cause the subsequent video to map the transformed image of the door to the entire area of the window, albeit somewhat distorted.
Using linear algebra is much easier than all that geometry! Plus you won't need to use sine, cosine, etc, so you can store each number as a rational fraction and get the exact numerical result if you need it.
What you want is a mapping from your old (x,y) co-ordinates to your new (x',y') co-ordinates. You can do it with matrices. You need to find the 2-by-4 projection matrix P such that P times the old coordinates equals the new co-ordinates. We'll assume that you're mapping lines to lines (not, for instance, straight lines to parabolas). Because you have a projection (parallel lines don't stay parallel) and translation (sliding), you need a factor of (xy) and (1), too. Drawn as matrices:
[x ]
[a b c d]*[y ] = [x']
[e f g h] [x*y] [y']
[1 ]
You need to know a through h so solve these equations:
a*x_0 + b*y_0 + c*x_0*y_0 + d = i_0
a*x_1 + b*y_1 + c*x_1*y_1 + d = i_1
a*x_2 + b*y_2 + c*x_2*y_2 + d = i_2
a*x_3 + b*y_3 + c*x_3*y_3 + d = i_3
e*x_0 + f*y_0 + g*x_0*y_0 + h = j_0
e*x_1 + f*y_1 + g*x_1*y_1 + h = j_1
e*x_2 + f*y_2 + g*x_2*y_2 + h = j_2
e*x_3 + f*y_3 + g*x_3*y_3 + h = j_3
Again, you can use linear algebra:
[x_0 y_0 x_0*y_0 1] [a e] [i_0 j_0]
[x_1 y_1 x_1*y_1 1] * [b f] = [i_1 j_1]
[x_2 y_2 x_2*y_2 1] [c g] [i_2 j_2]
[x_3 y_3 x_3*y_3 1] [d h] [i_3 j_3]
Plug in your corners for x_n,y_n,i_n,j_n. (Corners work best because they are far apart to decrease the error if you're picking the points from, say, user-clicks.) Take the inverse of the 4x4 matrix and multiply it by the right side of the equation. The transpose of that matrix is P. You should be able to find functions to compute a matrix inverse and multiply online.
Where you'll probably have bugs:
When computing, remember to check for division by zero. That's a sign that your matrix is not invertible. That might happen if you try to map one (x,y) co-ordinate to two different points.
If you write your own matrix math, remember that matrices are usually specified row,column (vertical,horizontal) and screen graphics are x,y (horizontal,vertical). You're bound to get something wrong the first time.
EDIT
The assumption below of the invariance of angle ratios is incorrect. Projective transformations instead preserve cross-ratios and incidence. A solution then is:
Find the point C' at the intersection of the lines defined by the segments AD and CP.
Find the point B' at the intersection of the lines defined by the segments AD and BP.
Determine the cross-ratio of B'DAC', i.e. r = (BA' * DC') / (DA * B'C').
Construct the projected line F'HEG'. The cross-ratio of these points is equal to r, i.e. r = (F'E * HG') / (HE * F'G').
F'F and G'G will intersect at the projected point Q so equating the cross-ratios and knowing the length of the side of the square you can determine the position of Q with some arithmetic gymnastics.
Hmmmm....I'll take a stab at this one. This solution relies on the assumption that ratios of angles are preserved in the transformation. See the image for guidance (sorry for the poor image quality...it's REALLY late). The algorithm only provides the mapping of a point in the quadrilateral to a point in the square. You would still need to implement dealing with multiple quad points being mapped to the same square point.
Let ABCD be a quadrilateral where A is the top-left vertex, B is the top-right vertex, C is the bottom-right vertex and D is the bottom-left vertex. The pair (xA, yA) represent the x and y coordinates of the vertex A. We are mapping points in this quadrilateral to the square EFGH whose side has length equal to m.
Compute the lengths AD, CD, AC, BD and BC:
AD = sqrt((xA-xD)^2 + (yA-yD)^2)
CD = sqrt((xC-xD)^2 + (yC-yD)^2)
AC = sqrt((xA-xC)^2 + (yA-yC)^2)
BD = sqrt((xB-xD)^2 + (yB-yD)^2)
BC = sqrt((xB-xC)^2 + (yB-yC)^2)
Let thetaD be the angle at the vertex D and thetaC be the angle at the vertex C. Compute these angles using the cosine law:
thetaD = arccos((AD^2 + CD^2 - AC^2) / (2*AD*CD))
thetaC = arccos((BC^2 + CD^2 - BD^2) / (2*BC*CD))
We map each point P in the quadrilateral to a point Q in the square. For each point P in the quadrilateral, do the following:
Find the distance DP:
DP = sqrt((xP-xD)^2 + (yP-yD)^2)
Find the distance CP:
CP = sqrt((xP-xC)^2 + (yP-yC)^2)
Find the angle thetaP1 between CD and DP:
thetaP1 = arccos((DP^2 + CD^2 - CP^2) / (2*DP*CD))
Find the angle thetaP2 between CD and CP:
thetaP2 = arccos((CP^2 + CD^2 - DP^2) / (2*CP*CD))
The ratio of thetaP1 to thetaD should be the ratio of thetaQ1 to 90. Therefore, calculate thetaQ1:
thetaQ1 = thetaP1 * 90 / thetaD
Similarly, calculate thetaQ2:
thetaQ2 = thetaP2 * 90 / thetaC
Find the distance HQ:
HQ = m * sin(thetaQ2) / sin(180-thetaQ1-thetaQ2)
Finally, the x and y position of Q relative to the bottom-left corner of EFGH is:
x = HQ * cos(thetaQ1)
y = HQ * sin(thetaQ1)
You would have to keep track of how many colour values get mapped to each point in the square so that you can calculate an average colour for each of those points.
I think what you're after is a planar homography, have a look at these lecture notes:
http://www.cs.utoronto.ca/~strider/vis-notes/tutHomography04.pdf
If you scroll down to the end you'll see an example of just what you're describing. I expect there's a function in the Intel OpenCV library which will do just this.
There is a C++ project on CodeProject that includes source for projective transformations of bitmaps. The maths are on Wikipedia here. Note that so far as i know, a projective transformation will not map any arbitrary quadrilateral onto another, but will do so for triangles, you may also want to look up skewing transforms.
If this transformation has to look good (as opposed to the way a bitmap looks if you resize it in Paint), you can't just create a formula that maps destination pixels to source pixels. Values in the destination buffer have to be based on a complex averaging of nearby source pixels or else the results will be highly pixelated.
So unless you want to get into some complex coding, use someone else's magic function, as smacl and Ian have suggested.
Here's how would do it in principle:
map the origin of A to the origin of B via a traslation vector t.
take unit vectors of A (1,0) and (0,1) and calculate how they would be mapped onto the unit vectors of B.
this gives you a transformation matrix M so that every vector a in A maps to M a + t
invert the matrix and negate the traslation vector so for every vector b in B you have the inverse mapping b -> M-1 (b - t)
once you have this transformation, for each point in the target area in B, find the corresponding in A and copy.
The advantage of this mapping is that you only calculate the points you need, i.e. you loop on the target points, not the source points. It was a widely used technique in the "demo coding" scene a few years back.