Related
I am trying to do vertical lines using Bresenham's Line Algorithm. But when I put coordinate for a vertical line, it is printing a point only, not showing a vertical line.
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
int main( )
{
int x1,y1,x2,y2,dx,dy,ds,dt,d,x,y;
/* request auto detection */
int gdriver = DETECT, gmode, errorcode;
/* initialize graphics and local variables */
initgraph(&gdriver, &gmode, "c:\\tc\\bgi");
x1=200;
x2=200;
y1=200;
y2=300;
x=x1;
y=y1;
dx=x2-x1;
dy=y2-y1;
dt=2*(dy-dx);
ds=2*dy;
d=2*dy-dx;
printf("Using Bresenham's Line Algorithm");
putpixel(x,y,7);
while(x<=x2)
{
x=x+1;
if(d<0)
d=d+ds;
else
{
y=y+1;
d=d+dt;
}
putpixel(x,y,7);
}
getch();
closegraph();
return 0;
}
When I put x1=200 x2=200 it gives me an error.
Why am I getting the error?
But in normal line function, I am getting the right result,
but when putting in Bresenham, I am getting the wrong result.
Bresenham like you implemented can only draw lines with a slope between 0° and 45° since every loop increases x by one and conditionally increases y by one.
What you have to do is first check if the line goes left to right. If not you have to switch the endpoints.
Next if the line slopes down instead of up you have to decrement y instead of incrementing it. You can store 1 or -1 in a temp variable depending on whether the lines slopes up or down and add that to y when needed.
And if the change in y is greater than the change in x you have to swap the coordinates around in the algorithm incrementing y every loop and x conditionally. For this you actually have to duplicate the whole loop.
I was doing the homework for computer graphics.
We need to use floodfill to paint an area, but no matter how I changed the reserve stack of Visual Studio, it would always jump out stackoverflow.
void Polygon_FloodFill(HDC hdc, int x0, int y0, int fillColor, int borderColor) {
int interiorColor;
interiorColor = GetPixel(hdc, x0, y0);
if ((interiorColor != borderColor) && (interiorColor != fillColor)) {
SetPixel(hdc, x0, y0, fillColor);
Polygon_FloodFill(hdc, x0 + 1, y0, fillColor, borderColor);
Polygon_FloodFill(hdc, x0, y0 + 1, fillColor, borderColor);
Polygon_FloodFill(hdc, x0 - 1 ,y0, fillColor, borderColor);
Polygon_FloodFill(hdc, x0, y0 - 1, fillColor, borderColor);
}
You may have too large an area to fill, which causes recursive calls to consume all of the execution stack in your program.
Your options:
grow the execution stack even further, if you can
reduce the area (how about just 100x100 or 20x20?)
stop using the execution stack and use a data structure that works similarly but can contain more elements (by being more efficient and/or being able to grow/be larger)
use a different algorithm (e.g. consider going from individual pixels to horizontal spans of pixels, there will be many fewer of the latter than the former)
What causes the stackoverflow?
What is the range of x0? +/- 2,000,000,000? That is your stack depth potential.
Code does not obviously prevent going out of range unless GetPixel(out-of-range) returns a no-match value.
And how can I resolve it?
Code needs to be more selective on recursive calls.
When a row of pixels can be set, do so without recursion.
Then examine that row's neighbors and only recurse when the neighbors were not continuously in need of setting.
A promising approach would handle the middle and then look at the 4 cardinal directions.
// Pseudo code
Polygon_FloodFill(x,y,c)
if (pixel(x,y) needs filling) {
set pixel(x,y,c);
for each of the 4 directions
// example: east
i = 1;
// fill the east line first
while (pixel(x+i,y) needs filling) {
i++;
set pixel(x,y,c);
}
// now examine the line above the "east" line
recursed = false;
for (j=1; j<i; j++) {
if (pixel(x+j, y+j) needs filling) {
if (!recursed) {
recursed = true;
Polygon_FloodFill(x+j,y+j,c)
} else {
// no need to call Polygon_FloodFill as will be caught with previous call
}
} else {
recursed = false;
}
}
// Same for line below the "east" line
// do same for south, west, north.
}
how many pixels to fill? each pixel is one level deep of recursion and you got a lot of variables all local ones and operands of the recursive function + return value and address so for reach pixel you store this:
void Polygon_FloodFill(HDC hdc, int x0, int y0, int fillColor, int borderColor) {
int interiorColor;
in 32 bit environment I estimate this in [Bytes]:
4 Polygon_FloodFill return address
4 HDC hdc ?
4 int x0
4 int y0
4 int fillColor
4 int borderColor
4 int interiorColor
-------------------
~ 7*4 = 28 Bytes
There might be even more depending on the C engine and calling sequence.
Now if your filled area has for example 256x256 pixel then you need:
7*4*256*256 = 1.75 MByte
of memory on the stack/heap. How much memory you got depends on the settings you compile/link with so go to project option and look for memory stack/heap limits...
How to deal with this?
lower the stack/heap trashing
simply do not use operands for your flood_fill instead move them to global variables:
HDC floodfill_hdc;
int floodfill_x0,floodfill_y0,floodfill_fillColor,floodfill_borderColor;
void _Polygon_FloodFill()
{
// here your original filling code
int interiorColor;
...
}
void PolygonFloodFill(HDC hdc, int x0, int y0, int fillColor, int borderColor) // this is what you call when want to fill something
{
floodfill_hdc=hdc;
floodfill_x0=x0;
floodfill_y0=y0;
floodfill_fillColor=fillColor;
floodfill_borderColor=borderColor;
_Polygon_FloodFill();
}
this will allow to fill ~14 times bigger area.
limit recursion depth
This is also sometimes called priority que ... You just add one gobal counter that is counting actual depth of recursion and if hit limit value then do not allow recursion. Instead add pixel position to some list that will be processed after actual recursion stops.
change filling from pixels to lines
this simply eliminates a lot of recursive calls in wildly rough estimate to sqrt(n) recursions from n... You simply fill whole line from a start point to predetermined direction until you hit the border ... So you would have just recursion call per each line instead of per pixel. Here example (see [edit2]):
Paint algorithm leaving white pixels at the edges when I color
However the function name Polygon_FloodFill implies you got the border polygon in vector form. If the case than filling it will be much faster using polygon rasterization techniques like:
how to rasterize rotated rectangle (in 2d by setpixel)
but for that the polygon must be convex one so if not the case you need to triangulate or break down to convex polygons first (for example with Ear clipping).
I'm trying to make an animation which will make a basic circle from dots. I got stuck, because i do not know how to make an array to auto-update herself to make an animation. My program has an issue, because it shows only the last point on circle and other, previous points has vanished due to system("clear") command, but i do not know how to make it the proper way.
Thanks in advance!
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(void){
char tab[43][132];
int a, b, t;
double x_kropki, y_kropki;
for (t=0 ; t<360 ; t++) {
x_kropki=floor(10*cos((t*pi)/180))+60;
y_kropki=floor(10*sin((t*pi)/180))+20;
for (a=0 ; a<43 ; a++, printf("\n")) for (b=0 ; b<132 ; b++) {
if ((int)y_kropki==a && (int)x_kropki==b){
tab[a][b]='.';
printf("%c", tab[a][b]);
}else {
tab[a][b]=' ';
printf("%c", tab[a][b]);
}
}
system("clear");
}
return 0;
}
What is the animation supposed to look like? Do you want the circle to grow slowly? Then you need to add a delay (sleep or similar) or else it will finish the whole process too quickly for the screen to draw and for your eyes to notice.
Also you should not clear the progress after every new dot (of the 360 dots in total, it seems). To achieve that, you will need to change your approach a bit. Here's what the loop could look like:
Draw nothing
Draw dot 1
Clear
Draw dot 1 and 2
Clear
Draw dot 1 and 2 and 3
You see that after clearing, you need to repeat printing the progress so far. At loop iteration 180, you need to print the last 179 dots again plus the 180th. Wait a few milliseconds, then clear, then the same for 181.
How you do that? You repeat the for loop:
int dot, maxDots;
for (maxDots = 0; maxDots < 360; maxDots++) {
for (dot = 0; dot < maxDots; dot++) {
// your location calculations and printing for each dot
}
system("clear");
}
This should at least give you some kind of growing circle. But you will notice that the printing approach is hard to get right, because once a line has been finished, you cannot go back. If you start at the top and go your way around 180 degrees, down line by line, you will then need to go up line by line until you reach the top again. That won't work easily. Instead of printing directly, as #Weather Vane suggested, store the to-be-printed result of each animation stage in a buffer. That is an abstraction of on-screen coordinates. A very simple approach would be a two-dimensional array that you can manipulate freely, then print the whole array en bloc.
The y values generated seem correct. See printf print out which prints increasing y vals. But when sent to SetPixel function it seems to print the sin e curve as if multiplied by -1???
What is wrong?
#include <windows.h>
//#include <stdio.h>
#include <math.h>
int main()
{
HWND console = GetConsoleWindow();
HDC dc = GetDC(console);
int pixel =0;
COLORREF C1= RGB(255,0,0); /* red */
for (double i = 0; i< 6.3; i+=0.05)
{
SetPixel(dc,pixel,(int)(100+50*sin(i)),C1);
/*printf("%d ", (int)(100+50*sin(i))); // prints numbers as expected, eg 100 102 104 107 109 112 etc */
pixel+=1;
}
ReleaseDC(console, dc);
return 0;
}
AFTER FEEDBACK
Due to Windows co-ordinate system starting (0,0) at top left you can just change sign of sin function like this:
SetPixel(dc,pixel,(int)(100+50*-sin(i)),C1);
That works.
The coordinate system isn't quite what you're expecting: y == 0 is the top, not the bottom, of the screen.
See Windows Coordinate System:
The x-coordinates increase to the right; y-coordinates increase from top to bottom.
The following illustrates it nicely (it talks about Java coordinates, but Windows coordinates are the same):
An easy way to work around this is to flip the sign of sin():
SetPixel(dc,pixel,(int)(100-50*sin(i)),C1);
↑
I am sorry for being this tedious but I reviewed my code several times with the help of a dozen of articles but still my KF doesn't work. By "doesn't work" I mean that the estimates by KF are wrong. Here is a nice paste of Real, Noised and KF estimated positions (just a small chunk).
My example is the same as in every tutorial I've found - I have a state vector of position and velocity. Position is in meters and represents vertical position in air. My real world case is skydiving (with parachute). In my sample generated data I've assumed we start at 3000m and the velocity is 10m/s.
P.S.: I am pretty sure matrix computations are OK - there must be an error with the logic.
Here I generate data:
void generateData(float** inData, float** noisedData, int x, int y){
inData[0][0]= 3000; //start position
inData[1][0]= -10; // 10m/s velocity; minus because we assume it's falling
noisedData[0][0]= 2998;
noisedData[1][0]= -10;
for(int i=1; i<x; i++){
inData[0][i]= inData[0][i-1] + inData[1][i-1];
inData[1][i]= inData[1][i-1]; //the velocity doesn't change for simplicity's sake
noisedData[0][i]=inData[0][i]+(rand()%6-3); //we add noise to real measurement
noisedData[1][i]=inData[1][i]; //velocity has no noise
}
}
And this is my implementation (matrices initialization is based on Wikipedia Kalman example):
int main(int argc, char** argv) {
srand(time(NULL));
float** inData = createMatrix(100,2); //2 rows, 100 columns
float** noisedData = createMatrix(100,2);
float** estData = createMatrix(100,2);
generateData(inData, noisedData, 100, 2);
float sampleRate=0.1; //10hz
float** A=createMatrix(2,2);
A[0][0]=1;
A[0][1]=sampleRate;
A[1][0]=0;
A[1][1]=1;
float** B=createMatrix(1,2);
B[0][0]=pow(sampleRate,2)/2;
B[1][0]=sampleRate;
float** C=createMatrix(2,1);
C[0][0]=1; //we measure only position
C[0][1]=0;
float u=1.0; //acceleration magnitude
float accel_noise=0.2; //acceleration noise
float measure_noise=1.5; //1.5 m standard deviation
float R=pow(measure_noise,2); //measure covariance
float** Q=createMatrix(2,2); //process covariance
Q[0][0]=pow(accel_noise,2)*(pow(sampleRate,4)/4);
Q[0][1]=pow(accel_noise,2)*(pow(sampleRate,3)/2);
Q[1][0]=pow(accel_noise,2)*(pow(sampleRate,3)/2);
Q[1][1]=pow(accel_noise,2)*pow(sampleRate,2);
float** P=createMatrix(2,2); //covariance update
P[0][0]=0;
P[0][1]=0;
P[1][0]=0;
P[1][1]=0;
float** P_est=createMatrix(2,2);
P_est[0][0]=P[0][0];
P_est[0][1]=P[0][1];
P_est[1][0]=P[1][0];
P_est[1][1]=P[1][1];
float** K=createMatrix(1,2); //Kalman gain
float** X_est=createMatrix(1,2); //our estimated state
X_est[0][0]=3000; X_est[1][0]=10;
// !! KALMAN ALGORITHM START !! //
for(int i=0; i<100; i++)
{
float** temp;
float** temp2;
float** temp3;
float** C_trans=matrixTranspose(C,2,1);
temp=matrixMultiply(P_est,C_trans,2,2,1,2); //2x1
temp2=matrixMultiply(C,P_est,2,1,2,2); //1x2
temp3=matrixMultiply(temp2,C_trans,2,1,1,2); //1x1
temp3[0][0]+=R;
K[0][0]=temp[0][0]/temp3[0][0]; // 1. KALMAN GAIN
K[1][0]=temp[1][0]/temp3[0][0];
temp=matrixMultiply(C,X_est,2,1,1,2);
float diff=noisedData[0][i]-temp[0][0]; //diff between meas and est
X_est[0][0]=X_est[0][0]+(K[0][0]*diff); // 2. ESTIMATION CORRECTION
X_est[1][0]=X_est[1][0]+(K[1][0]*diff);
temp=createMatrix(2,2);
temp[0][0]=1; temp[0][1]=0; temp[1][0]=0; temp[1][1]=1;
temp2=matrixMultiply(K,C,1,2,2,1);
temp3=matrixSub(temp,temp2,2,2,2,2);
P=matrixMultiply(temp3,P_est,2,2,2,2); // 3. COVARIANCE UPDATE
temp=matrixMultiply(A,X_est,2,2,1,2);
X_est[0][0]=temp[0][0]+B[0][0]*u;
X_est[1][0]=temp[1][0]+B[1][0]*u; // 4. PREDICT NEXT STATE
temp=matrixMultiply(A,P,2,2,2,2);
float** A_inv=getInverse(A,2);
temp2=matrixMultiply(temp,A_inv,2,2,2,2);
P_est=matrixAdd(temp2,Q,2,2,2,2); // 5. PREDICT NEXT COVARIANCE
estData[0][i]=X_est[0][0]; //just saving here for later to write out
estData[1][i]=X_est[1][0];
}
for(int i=0; i<100; i++) printf("%4.2f : %4.2f : %4.2f \n", inData[0][i], noisedData[0][i], estData[0][i]); // just writing out
return (EXIT_SUCCESS);
}
It looks like you are assuming a rigid body model for the problem. If that is the case, then for the problem you are solving, I would not put in the input u when you do the process update to predict the next state. Maybe I am missing something but the input u does not play any role in generating the data.
Let me put it another way, setting u to +1 looks like your model is assuming that the body should move in the +x direction because there is an input in that direction, but the measurement is telling it to go the other way. So if you put a lot of weight on the measurements, it's going to go in the -ve direction, but if you put a lot of weight on the model, it should go in the +ve direction. Anyway, based on the data generated, I don't see a reason for setting u to anything but zero.
Another thing, your sampling rate is 0.1 Hz, But when you generate data, you are assuming it's one second, since every sample, the position is changed by -10 meters per second.
Here is a matlab/octave implementation.
l = 1000;
Ts = 0.1;
y = 3000; %measurement to be fed to KF
v = -10; % METERS PER SECOND
t = [y(1);v]; % truth for checking if its working
for i=2:l
y(i) = y(i-1) + (v)*Ts;
t(:,i) = [y(i);v]; % copy to truth vector
y(i) = y(i) + randn; % noise it up
end
%%%%% Let the filtering begin!
% Define dynamics
A = [1, Ts; 0, 1];
B = [0;0];
C = [1,0];
% Steady State Kalman Gain computed for R = 0.1, Q = [0,0;0,0.1]
K = [0.44166;0.79889];
x_est_post = [3000;0];
for i=2:l
x_est_pre = A*x_est_post(:,i-1); % Process update! That is our estimate in case no measurement comes in.
%%% OMG A MEASUREMENT!
x_est_post(:,i) = x_est_pre + K*(-x_est_pre(1)+y(i));
end
You are doing a lot of weird array indexing.
float** A=createMatrix(2,2);
A[0][0]=1;
A[0][3]=sampleRate;
A[1][0]=0;
A[1][4]=1;
What is the expected outcome of indexing outside of the bounds of the array?