11
\$\begingroup\$

I want to make a fancy animation where a point travels around a rectangle. I want to find the point's position at a time t.

The rectangle is given by X, Y, Width and Height.

a rectangle, with a clockwise path around it

Is there an algorithm for this?

I've used sin/cos for circles. What's the equivalent approach for rectangles?

\$\endgroup\$
  • 1
    \$\begingroup\$ Not a complete answer, therefore a comment. I do not think you can split this buy 1/4 if you do not have a quad, but a rectangle. But what you can do, if you know the max time it should take to go around is: Calculate the circumference s and use the formula s/a=v to calculate your speed v. \$\endgroup\$ – M0rgenstern Sep 3 '15 at 10:24
15
\$\begingroup\$

I'll assume your t goes from 0 to 1. (If not, just multiply to scale it appropriately.)

rectangle interpolation

Figure out what proportion (01) each side is of the perimeter. (side length / total perimeter)

To find how much of every side is “filled in” at time t, iterate through sides, subtracting their proportions until t is depleted to a negative value. That last edge (which caused t to go negative) is filled by a proportion of (side length + remaining) / side length. The rest are not filled.

To get the exact vector position at t, multiply each side's vector by the proportion of that side that is filled, and add them.

This works for any polygon actually!

arbitrary polygon interpolation

\$\endgroup\$
2
\$\begingroup\$

The sine and cosine of t are respectively the y and x coordinate of a point on the circle forming an angle t with the x-axis. No need for that in a rectangle! A rectangle is made of four lines. If t goes from 0 to 1, it reach the point (px,py) at t==0 and to (qx,qy) at t==1 with the line given by:

(l(x),l(y)) = (t*qx + (1-t)*px, t*qy + (1-t)*py)

if instead of 0 and 1, you time goes from t0 to t1, you can normalize the time first and then apply the above formula.

(l(x),l(y)) = (  ((t-t0)/(t1-t0))*qx + ((t1-t)/(t1-t0))*px, ((t-t0)/(t1-t0))*qy + ((t1-t)/(t1-t0))*py  )

Now, for you rectangle, divide in four cases with an if for each edge that covers one of the span of time and apply a line movement.

Notice that if your rectangle is axis-aligned, you will always have either the x-value or the y value which is constant. For instance, for t between 0 and a/4 (and supposing (X,Y) is bottom left),

(l(x),l(y)) = ((4*t/a)*(X+Width) + (1-4*t/a)*(X), Y+Height)

Which is also equals to:

(l(x),l(y)) = (X + (1-4*t/a)*(Width), Y+Height)
\$\endgroup\$
1
\$\begingroup\$

I don't know if there is an actual algorithm for this, but I made one myself (Java):

int points = 4; // for a rectangle
double progress = 0.0; // 0.0 -> 1.0 (with 1.0 being 100%)
double pp = points * progress; // This calculation would otherwise be done multiple times

int p1 = Math.floor(pp);
int p2 = Math.ceil(pp);

while (p1 >= points) p1 -= points;
while (p2 >= points) p2 -= points;

double tmp = 2 * Math.PI / points;

int p1x = Math.cos(tmp * p1);
int p1y = Math.sin(tmp * p1);
int p2x = Math.cos(tmp * p2);
int p2y = Math.sin(tmp * p2);

double p = pp - Math.floor(pp);

int x = (1.0 - p) * p1x + p * p2x; // between -1.0 and 1.0
int y = (1.0 - p) * p2x + p * p2y; // between -1.0 and 1.0

if (p == 0.0) { // prevent a weird glitch when p = 0.0 (I think this is a glitch)
    x = p1x;
    y = p1y;
}

You should transform the x and y variables to get your animation as big or small as you want (by multiplying) and where you want (adding to / subtracting from x and y).

I haven't tested this code, but I think it should work. This should also work for any polygon with any number of points (you could also use a bit of the code to generate the polygon).

\$\endgroup\$
1
\$\begingroup\$

Given :

a=total time

perimeter = WIDTH *2 + HEIGTH * 2;

Given time T1 how to get P on perimeter (assuming rect position at 0,0)?

T1=T1%a; //use mod to have T1<a

distT1 = (T1*Perimeter)/a; //distance traveled in time T1

now some easy primary scool geometry and math (that hope you spare me) to obtain P.x and P.y from distT1

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.