Rotating a 2d array -> reversing a loop - c

I use the following code to rotate a bitmask (a packed 2d array). To be honest I do not have a firm grip of the algorithm used, I copied and modified the rotation code from the pygame library (where it was used to rotate surfaces). Due to the implementation of bitmask I can speed this rotation up a lot by reversing the inner loop. With that I mean, instead of doing foreach y { foreach x { ... } } I need to do foreach x { foreach y { ... } }. I have trouble reversing the loop because the trigonometry has to be adapted in a way I don't currently see at this moment.
Here's the code:
typedef struct bitmask {
int w,h;
BITMASK_W bits[1];
} bitmask_t;
bitmask_t* bitmask_rotate(const bitmask_t *mask, float angle) {
bitmask_t *newmask = NULL;
double radangle, sangle, cangle;
int isin, icos;
double cx, cy, sx, sy;
int x, y, ax, ay, xd, yd, dx, dy;
int nxmax, nymax, xmaxval, ymaxval;
radangle = angle * DEG_TO_RAD;
sangle = sin(radangle);
cangle = cos(radangle);
isin = (int)(sangle * 65536);
icos = (int)(cangle * 65536);
x = mask->w;
y = mask->h;
cx = cangle*x;
cy = cangle*y;
sx = sangle*x;
sy = sangle*y;
nxmax = (int) (MAX (MAX (MAX (fabs (cx + sy), fabs (cx - sy)), fabs (-cx + sy)), fabs (-cx - sy)));
nymax = (int) (MAX (MAX (MAX (fabs (sx + cy), fabs (sx - cy)), fabs (-sx + cy)), fabs (-sx - cy)));
newmask = bitmask_create(nxmax, nymax, 0);
if (!newmask) return NULL;
cy = newmask->h / 2;
xd = ((mask->w - newmask->w) << 15);
yd = ((mask->h - newmask->h) << 15);
ax = ((newmask->w) << 15) - (int)(cangle * ((newmask->w - 1) << 15));
ay = ((newmask->h) << 15) - (int)(sangle * ((newmask->w - 1) << 15));
xmaxval = ((mask->w) << 16) - 1;
ymaxval = ((mask->h) << 16) - 1;
for (y = 0; y < newmask->h; y++) {
dx = (ax + (isin * (cy - y))) + xd;
dy = (ay - (icos * (cy - y))) + yd;
for (x = 0; x < newmask->w; x++) {
if (!(dx < 0 || dy < 0 || dx > xmaxval || dy > ymaxval)) {
if (bitmask_getbit(mask, dx >> 16, dy >> 16)) {
bitmask_setbit(newmask, x, y);
}
}
dx += icos;
dy += isin;
}
}
return newmask;
}
Before people are going to ask "what have you tried?", I looped up rotating matrices on Wikipedia, and I could see what is going on there and how they implemented it in this algorithm (precalculate a starting dx and dy and then increment with icos and isin), but the bitshifts and parameters I don't understand (ax for example) make it hard for me to follow.

for (x = 0; x < newmask->w; x++) {
dx = (ax + (isin * cy + icos * x)) + xd;
dy = (ay - (icos * cy - isin * x)) + yd;
for (y = 0; y < newmask->h; y++) {
if (!(dx < 0 || dy < 0 || dx > xmaxval || dy > ymaxval)) {
if (bitmask_getbit(mask, dx >> 16, dy >> 16)) {
bitmask_setbit(newmask, x, y);
}
}
dx -= isin;
dy += icos;
}
}

Related

What is the time complexity of this square root calculation?

I needed a square root approximation in C so I looked up this post and got this following implementation:
float squareroot(float n)
{
float x = n;
float y = 1;
float e = 0.001; // Accuracy level
if (n == 0)
return 0;
while ((x - y) > e)
{
x = (x + y) / 2;
if (n == 0 || x == 0)
return 0;
y = n / x;
}
return x;
}
What is the time complexity of this?
Hint:
Observe that
(x[k+1] - √n)/(x[k+1] + √n) = (x[k] + n/x[k] - 2√n)/(x[k] + n/x[k] + 2√n)
= (x[k] - √n)²/(x[k] + √n)².
So by induction,
(x[k] - √n)/(x[k] + √n) = (x[0] - √n)^(2^k)/(x[0] + √n)^(2^k)
= (√n - 1)^(2^k)/(√n + 1)^(2^k).
From this we find the number of iterations after which the error is e:
k = lg(lg(e / (2√n - e)) / lg((√n - 1)/(√n + 1)).
(base-2 logarithm.)

What does the variable D do inside the while in this Bresenham's line drawing algorithm?

I've found this Generalized Bresenham's Line Drawing Algorithm and I'm having a hard time understanding what the while is doing here.
Any help is greatly appreciated.
the code:
#define sign(x) ((x > 0)? 1 : ((x < 0)? -1: 0))
x = x1;
y = y1;
dx = abs(x2 - x1);
dy = abs(y2 - y1);
s1 = sign(x2 - x1);
s2 = sign(y2 - y1);
swap = 0;
if (dy > dx) {
temp = dx;
dx = dy;
dy = temp;
swap = 1;
}
D = 2*dy - dx;
for (i = 0; i < dx; i++) {
display_pixel (x, y);
while (D >= 0) {
D = D - 2*dx;
if (swap)
x += s1;
else
y += s2;
}
D = D + 2*dy;
if (swap)
y += s2;
else
x += s1;
}
D is the scaled distance from the line to the candidate x, y coordinate.
Better: D is scaled difference of the distance from the line to the candidates x+1, y+0 and x+1, y+1.
That is, as x increments, the sign of D indicates should the closer y increment by 0 or 1?
(The role of x, y interchanges depending on which octant the algorithm is applied.)
I expected while (D >= 0) { as if (D >= 0) {. Bresenham's line algorithm
Note that OP's code is subject to overflow in abs(x2 - x1) and 2*dy - dx. Alternates exist that do not rely on wider math.

C function call Numerical Recipes Chapter 10.3

I have this function. I'm kinda green in C and I don't know how to call this function to get a result:
float dbrent(float ax, float bx, float cx, float (*f)(float),float (*df)(float), float tol, float* xmin)
{
int iter, ok1, ok2;
float a, b, d, d1, d2, du, dv, dw, dx, e = 0.0;
float fu, fv, fw, fx, olde, tol1, tol2, u, u1, u2, v, w, x, xm;
a = (ax < cx ? ax : cx);
b = (ax > cx ? ax : cx);
x = w = v = bx;
fw = fv = fx = (*f)(x);
dw = dv = dx = (*df)(x);
for (iter = 1; iter <= ITMAX; iter++)
{
xm = 0.5 * (a + b);
tol1 = tol * fabs(x) + ZEPS;
tol2 = 2.0 * tol1;
if (fabs(x - xm) <= (tol2 - 0.5 * (b - a))) {
*xmin = x;
return fx;
}
if (fabs(e) > tol1) {
d1 = 2.0 * (b - a);
d2 = d1;
if (dw != dx) d1 = (w - x) * dx / (dx - dw);
if (dv != dx) d2 = (v - x) * dx / (dx - dv);
u1 = x + d1;
u2 = x + d2;
ok1 = (a - u1) * (u1 - b) > 0.0 && dx * d1 <= 0.0;
ok2 = (a - u2) * (u2 - b) > 0.0 && dx * d2 <= 0.0;
olde = e;
e = d;
if (ok1 || ok2) {
if (ok1 && ok2)
d = (fabs(d1) < fabs(d2) ? d1 : d2);
else if (ok1)
d = d1;
else
d = d2;
if (fabs(d) <= fabs(0.5 * olde)) {
u = x + d;
if (u - a < tol2 || b - u < tol2)
d = SIGN(tol1, xm - x);
}
else {
d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
}
}
else {
d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
}
}
else {
d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
}
if (fabs(d) >= tol1) {
u = x + d;
fu = (*f)(u);
}
else {
u = x + SIGN(tol1, d);
fu = (*f)(u);
if (fu > fx) {
*xmin = x;
return fx;
}
}
du = (*df)(u);
if (fu <= fx) {
if (u >= x) a = x; else b = x;
MOV3(v, fv, dv, w, fw, dw)
MOV3(w, fw, dw, x, fx, dx)
MOV3(x, fx, dx, u, fu, du)
}
else {
if (u < x) a = u; else b = u;
if (fu <= fw || w == x) {
MOV3(v, fv, dv, w, fw, dw)
MOV3(w, fw, dw, u, fu, du)
}
else if (fu < fv || v == x || v == w) {
MOV3(v, fv, dv, u, fu, du)
}
}
}
cout<<"Too many iterations in routine dbrent";
return 0.0;
}
This code is from Numerical Recipes Chapter 10.3. I need to call this function and get the result but I don't know how to call it, especially when there is a syntax like float (*)(float).
Thanks in advance.
Well, let's suppose you have the following functions:
float df_(float yourFloat) {
...
return yourFloat;
}
and
float f_(float yourFloat) {
...
return yourFloat;
}
Then you could call your function as follows:
float t = dbrent(ax, bx, cx, &f_, &df_, tol, &xmin);
Where &xmin hands over the address of some float variable xmin.
So, in essence, you supply the address of your functions f_ and df_ and your float variable xmin.
We can call dbrent in several ways, the below shown is one of the ways.
Your function prototype
float dbrent ( float ax, float bx, float cx,
float (*f)(float),
float (*df)(float),
float tol, float* xmin
)
what you need is a func_f (you can use any name for function) that takes a float value as an argument and returns a float value as shown below.
float func_f(float num)
{
/* code */
}
you need one more function with same type as mentioned above
float func_df(float num)
{
/* code */
}
Following is the setup you need to make before calling dbrent
some_funtion()
{
// setup to call dbrent
// guess you know you need some values in it.
float ax, bx, cx, tol, xmin;
float (*f)(float);
float (*df)(float);
f = func_f;
df = func_df;
//one way of calling dbrent
dbrent(ax, bx, cx, f, df,tol, xmin);
//you can even directly call using the function names instead of using pointers
dbrent(ax, bx, cx, func_f, func_df, tol, xmin);
}
NOTE: variables have not been initialized for simplicity, make sure you pass valid variables when calling the function.

Perlin Noise Attempt

I am trying my attempt at Perlin Noise (3-dimensional) as outlined in this document: http://lodev.org/cgtutor/randomnoise.html
However, this is what I'm getting.
It looks like the smoothing isn't working. You can see blocks the size of the 'size' parameter. Can someone point out what I'm doing wrong?
Here's my code:
%ffp
ctl(1):standard,"Size",range=(1,256), pos=(300,20), size=(120,*),val=64,track, action=preview
onFilterStart:
{
allocArray(9,64,64,64,4); // Array for noise depth
for(int z = 0; z < 64; z++)
for(int y = 0; y < 64; y++)
for(int x = 0; x < 64; x++) {
fputArray(9,x,y,z,(float)(rand() % 32768) / 32768.0);
}
return false;
}
forEveryTile:
{
double fractX,fractY,fractZ,xx,yy,zz;
int x1,y1,z1,x2,y2,z2,col;
double value = 0.0, value2 = 0.0, size, isize=(float)ctl(1);
// int X=screen Width, int Y=screen Height
for(int y = 0; y < Y; y++) {
for(int x = 0; x < X; x++) {
//for(int z = 0; z < 64; z++) {
value2 = 0.0;
size = isize;
while (size >=1.0) {
xx=(float)x/size;
yy=(float)y/size;
zz=(float)clock()/size;
fractX = xx - (int)(xx);
fractY = yy - (int)(yy);
fractZ = zz - (int)(zz);
x1 = ((int)(xx) + 64) % 64;
y1 = ((int)(yy) + 64) % 64;
z1 = ((int)(zz) + 64) % 64;
x2 = (x1 + 64- 1) % 64;
y2 = (y1 + 64- 1) % 64;
z2 = (z1 + 64- 1) % 64;
value=0.0;
value += fractX * fractY * fractZ * fgetArray(9,z1,y1,x1);
value += fractX * (1 - fractY) * fractZ * fgetArray(9,z1,y2,x1);
value += (1 - fractX) * fractY * fractZ * fgetArray(9,z1,y1,x2);
value += (1 - fractX) * (1 - fractY) * fractZ * fgetArray(9,z1,y2,x2);
value += fractX * fractY * (1 - fractZ) * fgetArray(9,z2,y1,x1);
value += fractX * (1 - fractY) * (1 - fractZ) * fgetArray(9,z2,y2,x1);
value += (1 - fractX) * fractY * (1 - fractZ) * fgetArray(9,z2,y1,x2);
value += (1 - fractX) * (1 - fractY) * (1 - fractZ) * fgetArray(9,z2,y2,x2);
value2 += value*size;
size /= 2.0;
}
col=(int)((float)(128.0 * value2 / isize));
col=max(min(col,255),0);
psetp(x,y,RGB(col,col,col));
//} //z
} //x
} //y
return true;
}
Your code is kind of hard to read as written.
For Perlin noise start out with a integer noise function, that behaves like a hash.
float noise(int x, int y, int z) { return hash(x+y*5+z*7); }
or
float noise(int x, int y, int z) { return array[x%w+y%h*w+z%d*w*h]; }
Those are just examples. The important part is that noise(x,y,z) = noise(x,y,z). The noise function has to return the same value for the same parameters every time.
There is a problem though: The noise function only takes integer parameters! But we would like to sample it at float values.
float noisesample (float x, float y, float z) { ... }
The easiest way to to that is using linear filtering. Any positive float value is between (int)pos and ((int)pos)+1. At sub-position pos-(int)pos. This gets us:
float Lerp(float a, float b, float f) { return a+(b-a)*f; }
Where f is the sub-position in the [0..1] range and a,b are the values to the left and right. If f is 0, Lerp returns a, if it is 1, it returns b. In between it does linear interpolation.
So use this for a simple 1D noisesample function:
float noisesample(float x) { return Lerp(noise((int)x), noise((int)x+1), fract(x) }
with
float fract(float x) { return x-(int)x; }
I am using (int)x liberally here, it is the same as floor(x) if x is positive.
To go from a single parameter noisesample to x,y is easy: Do the Lerp twice for x at y and y+1, and Lerp between those:
float noisesample(float x, float y) {
float y0 = Lerp(noise((int)x,(int)y), noise((int)x+1,(int)y), fract(x) }
float y1 = Lerp(noise((int)x,(int)y+1), noise((int)x+1,(int)y+1), fract(x) }
return Lerp ( y0, y1, fract(y) );
}
First interpolate x, twice, then interpolate between the results in y. In total we sample noise() 4 times. I leave it as an exercise how to write noisesample ( float x, float y, float z). It will sample noise() eight times and call Lerp 7 times.
All that got us is that we can sample noise (somewhat smooth - there are smoother ways!) at float coordinates. And that is what we need to make perlin noise!
float perlin(float x, float y, float z, int oc=4) {
// maybe: x = x*2^oc, y, z...
float r = 0;
float s = 1;
for ( int i=0; i<oc; i++ ) {
r += noisesample(x,y,z) * s;
s/=2.0f; // to taste
x/=2.0f;
y/=2.0f;
z/=2.0f;
}
return r;
}
The key idea is to understand sampling. It's just a combination of sampling a simple integer noise function.

Detecting if angle is more than 180 degrees

I'm working on a problem that the professor assigned, and I'm having a problem looking for a way to detect if the angle between 3 points is more than 180 degrees, e.g:
I want to detect if alpha is more than 180 degrees. Anyways, my professor has a code that solves the problem, but he has a function called zcross, but I don't exactly know how it works. Could anyone tell me? His code is here:
#include <fstream.h>
#include <math.h>
#include <stdlib.h>
struct point {
double x;
double y;
double angle;
};
struct vector {
double i;
double j;
};
point P[10000];
int hull[10000];
int
zcross (vector * u, vector * v)
{
double p = u->i * v->j - v->i * u->j;
if (p > 0)
return 1;
if (p < 0)
return -1;
return 0;
}
int
cmpP (const void *a, const void *b)
{
if (((point *) a)->angle < ((point *) b)->angle)
return -1;
if (((point *) a)->angle > ((point *) b)->angle)
return 1;
return 0;
}
void
main ()
{
int N, i, hullstart, hullend, a, b;
double midx, midy, length;
vector v1, v2;
ifstream fin ("fc.in");
fin >> N;
midx = 0, midy = 0;
for (i = 0; i < N; i++) {
fin >> P[i].x >> P[i].y;
midx += P[i].x;
midy += P[i].y;
}
fin.close ();
midx = (double) midx / N;
midy = (double) midy / N;
for (i = 0; i < N; i++)
P[i].angle = atan2 (P[i].y - midy, P[i].x - midx);
qsort (P, N, sizeof (P[0]), cmpP);
hull[0] = 0;
hull[1] = 1;
hullend = 2;
for (i = 2; i < N - 1; i++) {
while (hullend > 1) {
v1.i = P[hull[hullend - 2]].x - P[hull[hullend - 1]].x;
v1.j = P[hull[hullend - 2]].y - P[hull[hullend - 1]].y;
v2.i = P[i].x - P[hull[hullend - 1]].x;
v2.j = P[i].y - P[hull[hullend - 1]].y;
if (zcross (&v1, &v2) < 0)
break;
hullend--;
}
hull[hullend] = i;
hullend++;
}
while (hullend > 1) {
v1.i = P[hull[hullend - 2]].x - P[hull[hullend - 1]].x;
v1.j = P[hull[hullend - 2]].y - P[hull[hullend - 1]].y;
v2.i = P[i].x - P[hull[hullend - 1]].x;
v2.j = P[i].y - P[hull[hullend - 1]].y;
if (zcross (&v1, &v2) < 0)
break;
hullend--;
}
hull[hullend] = i;
hullstart = 0;
while (true) {
v1.i = P[hull[hullend - 1]].x - P[hull[hullend]].x;
v1.j = P[hull[hullend - 1]].y - P[hull[hullend]].y;
v2.i = P[hull[hullstart]].x - P[hull[hullend]].x;
v2.j = P[hull[hullstart]].y - P[hull[hullend]].y;
if (hullend - hullstart > 1 && zcross (&v1, &v2) >= 0) {
hullend--;
continue;
}
v1.i = P[hull[hullend]].x - P[hull[hullstart]].x;
v1.j = P[hull[hullend]].y - P[hull[hullstart]].y;
v2.i = P[hull[hullstart + 1]].x - P[hull[hullstart]].x;
v2.j = P[hull[hullstart + 1]].y - P[hull[hullstart]].y;
if (hullend - hullstart > 1 && zcross (&v1, &v2) >= 0) {
hullstart++;
continue;
}
break;
}
length = 0;
for (i = hullstart; i <= hullend; i++) {
a = hull[i];
if (i == hullend)
b = hull[hullstart];
else
b = hull[i + 1];
length += sqrt ((P[a].x - P[b].x) * (P[a].x - P[b].x) + (P[a].y - P[b].y) * (P[a].y - P[b].y));
}
ofstream fout ("fc.out");
fout.setf (ios: :fixed);
fout.precision (2);
fout << length << '\n';
fout.close ();
}
First, we know that if sin(a) is negative, then the angle is more than 180 degrees.
How do we find the sign of sin(a)? Here is where cross product comes into play.
First, let's define two vectors:
v1 = p1-p2
v2 = p3-p2
This means that the two vectors start at p2 and one points to p1 and the other points to p3.
Cross product is defined as:
(x1, y1, z1) x (x2, y2, z2) = (y1z2-y2z1, z1x2-z2x1, x1y2-x2y1)
Since your vectors are in 2d, then z1 and z2 are 0 and hence:
(x1, y1, 0) x (x2, y2, 0) = (0, 0, x1y2-x2y1)
That is why they call it zcross because only the z element of the product has a value other than 0.
Now, on the other hand, we know that:
||v1 x v2|| = ||v1|| * ||v2|| * abs(sin(a))
where ||v|| is the norm (size) of vector v. Also, we know that if the angle a is less than 180, then v1 x v2 will point upwards (right hand rule), while if it is larger than 180 it will point down. So in your special case:
(v1 x v2).z = ||v1|| * ||v2|| * sin(a)
Simply put, if the z value of v1 x v2 is positive, then a is smaller than 180. If it is negative, then it's bigger (The z value was x1y2-x2y1). If the cross product is 0, then the two vectors are parallel and the angle is either 0 or 180, depending on whether the two vectors have respectively same or opposite direction.
zcross is using the sign of the vector cross product (plus or minus in the z direction) to determine if the angle is more or less than 180 degrees, as you've put it.
In 3D, find the cross product of the vectors, find the minimum length for the cross product which is basically just finding the smallest number of x, y and z.
If the smallest value is smaller than 0, the angle of the vectors is negative.
So in code:
float Vector3::Angle(const Vector3 &v) const
{
float a = SquareLength();
float b = v.SquareLength();
if (a > 0.0f && b > 0.0f)
{
float sign = (CrossProduct(v)).MinLength();
if (sign < 0.0f)
return -acos(DotProduct(v) / sqrtf(a * b));
else
return acos(DotProduct(v) / sqrtf(a * b));
}
return 0.0f;
}
Another way to do it would be as follows:
calculate vector v1=p2-p1, v2 = p2 -p3.
Then, use the cross-product formula : u.v = ||u|| ||v|| cos(theta)

Resources