C++ Coordinate Generation - c++

I will try to explain what I need as best as I can.
I am creating a snake game with a gui, and I need the fruit to randomly spawn. I can get it to spawn on any random coordinate within the game. But that's no good, since the snake only travels on coordinates that are multiples of 10. This is because when you click any arrow key, it continuously adds 10 to to the previous coordinate. Basically, I need to have the fruit not only randomly spawn withing the boundaries, but also within coordinates that are a multiple of 10 so that the snake can actually collide with it no matter where it is on the map.
Size of map:
Width of map = 800
height of map = 500
I tried using a for loop like this (for the x coordinate):
for(int x = 0; x <= 800; x += 10)
and this for the y coord:
for(int y = 0; y <= 500; y += 10)
But I couldn't get anything to work. Once again, I need to generate a random x coordinate between 0 and 800 (0, 10, 20, 30, etc.) and a random y coordinate between 0 and 500 (0, 10, 20, etc.). If you understand what I'm getting at, because I'm not sure how well I've explained, please help out.
Thanks!

Generate number between 0-80, 0-50 and multiply by 10 each coordinate.

Divide your dimension by 10, generate a random number in that range, then multiply by 10.
For example, your x coordinate can be generated by creating a value between 0 and 80, then multiplying the result by 10.

your random generator
int iRandX = (rand() % 80) * 10;
int iRandY = (rand() % 50) * 10;

Related

Using Standard Cartesian Circle formula to draw circle in graphics mode (C++)

I wanted to draw a circle using graphics.h in C++, but not directly using the circle() function. The circle I want to draw uses smaller circles as it's points i.e. The smaller circles would constitute the circumference of the larger circle. So I thought, if I did something like this, it would work:
{
int radius = 4;
// Points at which smaller circles would be drawn
int x, y;
int maxx = getmaxx();
int maxy = getmaxy();
// Co-ordinates of center of the larger circle (centre of the screen)
int h = maxx/2;
int k = maxy/2;
//Cartesian cirle formula >> (X-h)^2 + (Y-k)^2 = radius^2
//Effectively, this nested loop goes through every single coordinate on the screen
int gmode = DETECT;
int gdriver;
initgraph(&gmode, &gdriver, "");
for(x = 0; x<maxx; x++)
{
for(y = 0; y<maxy; y++)
{
if((((x-h)*(x-h)) + ((y-k)*(y-k))) == (radius*radius))
{
circle(x, y, 5) //Draw smaller circle with radius 5
} //at points which satisfy circle equation only!
}
}
getch();
}
This is when I'm using graphics.h on Turbo C++ as this is the compiler we're learning with at school.
I know it's ancient.
So, theoretically, since the nested for loops check all the points on the screen, and draw a small circle at every point that satisfies the circle equation only, I thought I would get a large circle of radius as entered, whose circumference constitutes of the smaller circles I make in the for loop.
However, when I try the program, I get four hyperbolas (all pointing towards the center of the screen) and when I increase the radius, the pointiness (for lack of a better word) of the hyperbolas increase, until finally, when the radius is 256 or more, the two hyperbolas on the top and bottom intersect to make a large cross on my screen like : "That's it, user, I give up!"
I came to the value 256 as I noticed that of the radius was a multiple of 4 the figures looked ... better?
I looked around for a solution for quite some time, but couldn't get any answers, so here I am.
Any suggestions???
EDIT >> Here's a rough diagram of the output I got...
There are two issues in your code:
First: You should really call initgraph before you call getmaxx and getmaxy, otherwise they will not necessarily return the correct dimensions of the graphics mode. This may or may not be a contributing factor depending on your setup.
Second, and most importantly: In Turbo C++, int is 16-bit. For example, here is circle with radius 100 (after the previous initgraph order issue was fixed):
Note the stray circles in the four corners. If we do a little debugging and add some print-outs (a useful strategy that you should file away for future reference):
if((((x-h)*(x-h)) + ((y-k)*(y-k))) == (radius*radius))
{
printf(": (%d-%d)^2 + (%d-%d)^2 = %d^2\n", x, h, y, k, radius);
circle(x, y, 5); //Draw smaller circle with radius
} //at points which satisfy circle equation only!
You can see what's happening (first line is maxx and maxy, not shown in above snippet):
In particular that circle at (63, 139) is one of the corners. If you do the math, you see that:
(63 - 319)2 + (139 - 239)2 = 75536
And since your ints are 16-bit, 75536 modulo 65536 = 10000 = the value that ends up being calculated = 1002 = a circle where it shouldn't be.
An easy solution to this is to just change the relevant variables to long:
maxx, maxy
x, y
h, k
So:
long x, y;
...
initgraph(...);
...
long maxx = getmaxx();
long maxy = getmaxy();
...
long h = maxx / 2;
long k = maxy / 2;
And then you'll end up with correct output:
Note of course that like other answers point out, since you are using ints, you'll miss a lot of points. This may or may not be OK, but some values will produce noticeably poorer results (e.g. radius 256 only seems to have 4 integer solutions). You could introduce a tolerance if you want. You could also use a more direct approach but that might defeat the purpose of your exercise with the Cartesian circle formula. If you're into this sort of thing, here is a 24-page document containing a bunch of discussion, proofs, and properties about integers that are the sum of two squares.
I don't know enough about Turbo C++ to know if you can make it use 32-bit ints, I'll leave that as an exercise to you.
First of all, maxx and maxy are integers, which you initialize using some functions representing the borders of the screen and then later you use them as functions. Just remove the paranthesis:
// Co-ordinates of center of the larger circle (centre of the screen)
int h = maxx/2;
int k = maxy/2;
Then, you are checking for exact equality to check whether a point is on a circle. Since the screen is a grid of pixels, many of your points will be missed. You need to add a tolerance, a maximum distance between the point you check and the actual circle. So change this line:
if(((x-h)*(x-h)) + ((y-k)*(y-k)) == radius*radius)
to this:
if(abs(((x-h)*(x-h)) + ((y-k)*(y-k)) - radius*radius) < 2)
Introduction of some level of tolerance will solve the problem.
But it is not wise to check all the points in graphical window. Would you change an approach? You can draw needed small circles without checks at all:
To fill all big circle circumference (with RBig radius), you need NCircles small circles with RSmall radius
NCircles = round to integer (Pi / ArcSin(RSmall / RBig));
Center of i-th small circle is at position
cx = mx + Round(RBig * Cos(i * 2 * Pi / N));
cy = my + Round(RBig * Sin(i * 2 * Pi / N));
where mx, my - center of the big circle

Flattened 3D array interior values

I have a flattened 3D array representing the vertex indices of a procedural mesh that I'm trying to optimize. I create the array like so:
int* vertIndices = new int[WIDTH * HEIGHT * DEPTH];
and to add to the array
vertIndices[x + WIDTH * (y + HEIGHT * z)] = vertIndex;
The issue is that I only need to keep track of the vertices on the surface of the mesh. Interior vertices do not get created.
Therefore, I'm creating a lot of wasted integers that never get used.
Here is a loop through the vertIndices array of a mesh with WIDTH: 7, HEIGHT: 7 and DEPTH: 7
All those -1163005939 values are vertices that would be located within the interior of the mesh but do not get created.
My question is how can I improve the formula
x + WIDTH * (y + HEIGHT * z)
to ignore interior values.
Thanks!
I think you won't get around of introducing some kind of condition to the formula. Something like this:
int getIndex(int x, int y, int z) {
//First get the amount of points in all layers before this z layer.
int beforeZ = (z) ? WIDTH*HEIGHT + (z - 1)*2*(WIDTH + HEIGHT - 2) : 0;
//Then get the amount of points within this layer before this line.
int beforeY = (y) ? WIDTH + 2*(y - 1) : 0;
if(z == 0 || z == DEPTH - 1) beforeY = y*WIDTH;
//And finally the amount of points within this line before this point.
int beforeX = (x) ? 1 : 0;
if(z == 0 || z == DEPTH - 1 || y == 0 || y == HEIGHT - 1) beforeX = x;
//Return the amount of points before this one.
return beforeZ + beforeY + beforeX;
}
I admit that this is a bit ugly, but I think it's quite close to the best you can get. At least if you don't want to create some kind of lookup table that matches coordinates to indices and vice versa. Such lookup tables would, of course, be the really big gun that can handle any case, with the drawback of quite significant memory usage and likely slower operation.

Draw circles using for-loop Qt c++

I want to draw 7 circles using Qt in C++
I want to use a for loop;
However, I am unable to, I actually wanted to used the width of the window to equally space my circles which is not working out as well. Where am I wrong. I am new to programming. :)
Here is my code:
for (int i = 0; i <= 6;i++)
{
int x = 0;
int y = (width()/6);
x =y+x;
canvas.drawEllipse(x, 40, 20, 20);
}
Okay I was working on it and now I have five circles with this code
int x = 0;
for (int i = 0; i <= 6;i++)
{
x = x+(width()/6);
canvas.drawEllipse(x, 40, 20, 20);
}
But I want the first circle to start at
canvas.drawEllipse(0, 40, 20, 20);
In addition how can I change the color of one circle if I am switching from one page to another. Its an application with about 7 pages and each circle would represent a page so for example if I am on page 1 circle 1 should be green.
I have been told to create a function for this but how do I go about it referencing my pages and the circles. Thanks.
Let's do some math here.
Let Screen_Width be the width of the screen, in pixels.
Let Screen_Height be the height of the screen, in pixels.
The width of an ideal circle is the same as the diameter, or 2 * radius.
However, this is reality, sow we have to account for line widths.
So the actual width of a circle is: Diameter + 2 * Circle_Line_Width;
Also, this being reality and not ideal conditions, we would like spacing between the circles.
Let Spacing be the distance, in pixels between the outer lines of the circles.
Let Circle_Quantity be the number of circles.
So, the total width occupied by the circle is:
Circle_Width = Diameter + 2 * Circle_Line_Width + (Space_Between_Circles / 2);
The space available for a circle (with spacing) is:
Available_Circle_Space = Screen_Width / Circle_Quantity;
Now comes the trick, locating the centers of the circles.
Let's find out the values of the circle properties.
Solving for the diameter:
Diameter = Circle_Width / (2 * Circle_Line_Width + (Space_Between_Circles/2));
Remember, the center of the circle will be the midpoint of the diameter, which is Diameter / 2.
So, the first center point is:
0 /*Left edge ordinate */
+ (Space_Between_Circles/2)
+ Circle_Line_Width
+ (Diameter / 2)
The next center point is at:
Previous_Center_Point
+ (Space_Between_Circles/2)
+ Circle_Line_Width
+ (Diameter / 2)
This should show you how to make a for loop to draw all the circles.
Switch around the two statements in the loop:
int x = 0;
for (int i = 0; i <= 6;i++)
{
canvas.drawEllipse(x, 40, 20, 20); //0 on 1st iteration
x = x+(width()/6); //x = 0 + (width()/6), which will be used on 2nd iteration, etc.
}
To use x as 0 in the first loop, you save adding width()/6 until after you've first used it.

super mysterious logic error for a planar fitting image processing algorithm

so i have this image processing program where i am using a linear regression algorithm to find a plane that best fits all of the points (x,y,z: z being the pixel color intensity (0-255)
Simply speaking i have this picture of ? x ? dimension. I run this algorithm and i get these A, B, C values. (3 float values)
then i go every pixel in the program and minus the pixel value with mod_val where
mod_val = (-A * x -B * y ) / C
A,B,C are constants while x,y is the pixel location in a x,y plane.
When the dimension of the picture is divisible by 100 its perfect but when its not the picture fractures. The picture itself is the same as the original but there is a diagonal line with color contrast that goes across the picture. The program is supposed to make the pixel color uniform from the center.
I tried running the picture where mod_val = 0 for not divisble by 100 dimension pictures and it copies a new picture perfectly. So i doubt there is a problem with storing and writing the read data in terms of alignment. (fyi this picture is a grey scale 8 bit.bmp)
I have tried changing the A,B,C values but the diagonal remains the same. The color of the image fragments within the diagonals change.
when i run 1400 x 1100 picture it works perfectly with the mod_val equation written above which is the most baffling part.
I spent a lot of time looking for rounding errors. They are virtually all floats. The dimension i used for breaking picture is 1490 x 1170.
here is a gragment of the code where i think a error is occuring:
int img_row = row_length;
int img_col = col_length;
int i = 0;
float *pfAmultX = new float[img_row];
for (int x = 0; x < img_row; x++)
{
pfAmultX[x] = (A * x)/C;
}
for (int y = 0; y < img_col; y++)
{
float BmultY = B*y/C;
for (int x = 0; x < img_row; x++, i++)
{
modify_val = pfAmultX[x] + BmultY;
int temp = (int) data.data[i];
data.data[i] += (unsigned char) modify_val;
if(temp >= 250){
data.data[i] = 255;
}
else if(temp < 0){
data.data[i] = 0;
}
}
}
delete[] pfAmultX;
The img_row, img_col is correct according to VS debugger mode
Any help would be greatly appreciated. I've been trying to find this bug for many hours now and my boss is telling me that i can't go back home until i find this bug.....
before algorithm (1400 x 1100, works)
after
before (1490 x 1170, demonstrates the problem)
after
UPDATE:
well i have boiled down the problem as something with the x coordinate after extensive testing.
This is because when i use large A or B values or both (C value is always ~.999) for 1400x1100 it does not create diagonals.
However, for the other image, large B values do not create diagonals but a fairly small - avg A value creates diagonals.
Whats even more, when i test a picture where x is disivible by 100 but y is divisible by 10. the answer is correct.
well in the end i found the solution. It was a problem due to the padding the the bitmap. When the dimension on the x was not divisible by 4 it would use padding which would throw off all of the x coordinates. This also meant that the row_value i received from the bmp header was the same as the dimension but not really the same in reality. I had to make a edit where i had to do: 4 * (row_value_from_bmp_header + 3)/ 4.

Optimized float Blur variations

I am looking for optimized functions in c++ for calculating areal averages of floats. the function is passed a source float array, a destination float array (same size as source array), array width and height, "blurring" area width and height.
The function should "wrap-around" edges for the blurring/averages calculations.
Here is example code that blur with a rectangular shape:
/*****************************************
* Find averages extended variations
*****************************************/
void findaverages_ext(float *floatdata, float *dest_data, int fwidth, int fheight, int scale, int aw, int ah, int weight, int xoff, int yoff)
{
printf("findaverages_ext scale: %d, width: %d, height: %d, weight: %d \n", scale, aw, ah, weight);
float total = 0.0;
int spos = scale * fwidth * fheight;
int apos;
int w = aw;
int h = ah;
float* f_temp = new float[fwidth * fheight];
// Horizontal
for(int y=0;y<fheight ;y++)
{
Sleep(10); // Do not burn your processor
total = 0.0;
// Process entire window for first pixel (including wrap-around edge)
for (int kx = 0; kx <= w; ++kx)
if (kx >= 0 && kx < fwidth)
total += floatdata[y*fwidth + kx];
// Wrap
for (int kx = (fwidth-w); kx < fwidth; ++kx)
if (kx >= 0 && kx < fwidth)
total += floatdata[y*fwidth + kx];
// Store first window
f_temp[y*fwidth] = (total / (w*2+1));
for(int x=1;x<fwidth ;x++) // x width changes with y
{
// Substract pixel leaving window
if (x-w-1 >= 0)
total -= floatdata[y*fwidth + x-w-1];
// Add pixel entering window
if (x+w < fwidth)
total += floatdata[y*fwidth + x+w];
else
total += floatdata[y*fwidth + x+w-fwidth];
// Store average
apos = y * fwidth + x;
f_temp[apos] = (total / (w*2+1));
}
}
// Vertical
for(int x=0;x<fwidth ;x++)
{
Sleep(10); // Do not burn your processor
total = 0.0;
// Process entire window for first pixel
for (int ky = 0; ky <= h; ++ky)
if (ky >= 0 && ky < fheight)
total += f_temp[ky*fwidth + x];
// Wrap
for (int ky = fheight-h; ky < fheight; ++ky)
if (ky >= 0 && ky < fheight)
total += f_temp[ky*fwidth + x];
// Store first if not out of bounds
dest_data[spos + x] = (total / (h*2+1));
for(int y=1;y< fheight ;y++) // y width changes with x
{
// Substract pixel leaving window
if (y-h-1 >= 0)
total -= f_temp[(y-h-1)*fwidth + x];
// Add pixel entering window
if (y+h < fheight)
total += f_temp[(y+h)*fwidth + x];
else
total += f_temp[(y+h-fheight)*fwidth + x];
// Store average
apos = y * fwidth + x;
dest_data[spos+apos] = (total / (h*2+1));
}
}
delete f_temp;
}
What I need is similar functions that for each pixel finds the average (blur) of pixels from shapes different than rectangular.
The specific shapes are: "S" (sharp edges), "O" (rectangular but hollow), "+" and "X", where the average float is stored at the center pixel on destination data array. Size of blur shape should be variable, width and height.
The functions does not need to be pixelperfect, only optimized for performance. There could be separate functions for each shape.
I am also happy if anyone can tip me of how to optimize the example function above for rectangluar blurring.
What you are trying to implement are various sorts of digital filters for image processing. This is equivalent to convolving two signals where the 2nd one would be the filter's impulse response. So far, you regognized that a "rectangular average" is separable. By separable I mean, you can split the filter into two parts. One that operates along the X axis and one that operates along the Y axis -- in each case a 1D filter. This is nice and can save you lots of cycles. But not every filter is separable. Averaging along other shapres (S, O, +, X) is not separable. You need to actually compute a 2D convolution for these.
As for performance, you can speed up your 1D averages by properly implementing a "moving average". A proper "moving average" implementation only requires a fixed amount of little work per pixel regardless of the averaging "window". This can be done by recognizing that neighbouring pixels of the target image are computed by an average of almost the same pixels. You can reuse these sums for the neighbouring target pixel by adding one new pixel intensity and subtracting an older one (for the 1D case).
In case of arbitrary non-separable filters your best bet performance-wise is "fast convolution" which is FFT-based. Checkout www.dspguide.com. If I recall correctly, there is even a chapter on how to properly do "fast convolution" using the FFT algorithm. Although, they explain it for 1-dimensional signals, it also applies to 2-dimensional signals. For images you have to perform 2D-FFT/iFFT transforms.
To add to sellibitze's answer, you can use a summed area table for your O, S and + kernels (not for the X one though). That way you can convolve a pixel in constant time, and it's probably the fastest method to do it for kernel shapes that allow it.
Basically, a SAT is a data structure that lets you calculate the sum of any axis-aligned rectangle. For the O kernel, after you've built a SAT, you'd take the sum of the outer rect's pixels and subtract the sum of the inner rect's pixels. The S and + kernels can be implemented similarly.
For the X kernel you can use a different approach. A skewed box filter is separable:
You can convolve with two long, thin skewed box filters, then add the two resulting images together. The center of the X will be counted twice, so will you need to convolve with another skewed box filter, and subtract that.
Apart from that, you can optimize your box blur in many ways.
Remove the two ifs from the inner loop by splitting that loop into three loops - two short loops that do checks, and one long loop that doesn't. Or you could pad your array with extra elements from all directions - that way you can simplify your code.
Calculate values like h * 2 + 1 outside the loops.
An expression like f_temp[ky*fwidth + x] does two adds and one multiplication. You can initialize a pointer to &f_temp[ky*fwidth] outside the loop, and just increment that pointer in the loop.
Don't do the division by h * 2 + 1 in the horizontal step. Instead, divide by the square of that in the vertical step.