Passing char * as an argument - c++

I've got a problem in my code. I'm rewriting an existing module that draw graph (from electrical consomation) with GDI+ (yes Visual Studio Microsoft and co)
Here is my code to draw one graph
void CourbeComptage::afficheCourbeJour_nonEDF(CWnd *cwnd)
{
dessin ligne,rectangle,texte;
int i;
int lx = x + margeH;
int ly = y + haut - margeV;
int x1, y1, x2, y2;
if(flagCourbe)
{
afficheGraduation();
// 4 - tracer la courbe de consommation avec des plages horaires
for(i=0;i<24;i++)
{
x1 = lx + i * pasX;
y1 = ly - coorX_conso[i];
x2 = lx + (i + 1) * pasX;
y2 = ly - 1;
plage[i] = (plage[i] > 3) ? 3 : (plage[i] < 1) ? 1 : plage[i];
if(typeCourbe == COURBE_BARRE_3D)
{
drawer->DrawFilledGradientRectangle(x1, y1, x2, y2, gradient[plage[i]], "transparent", 1);
switch(plage[i])
{
case 1: drawer->DrawFilledGradientRectangle(x1, y1, x2, y2, "conso_HC", "transparent", 1); break;
case 2: drawer->DrawFilledGradientRectangle(x1, y1, x2, y2, "conso_HP", "transparent", 1); break;
case 3: drawer->DrawFilledGradientRectangle(x1, y1, x2, y2, "conso_P", "transparent", 1); break;
}
}
else if(typeCourbe == COURBE_BARRE)
{
switch(plage[i])
{
case 1: drawer->DrawFilledSolidRectangle(x1, y1, x2, y2, "conso2_HC", "transparent", 1); break;
case 2: drawer->DrawFilledSolidRectangle(x1, y1, x2, y2, "conso2_HP", "transparent", 1); break;
case 3: drawer->DrawFilledSolidRectangle(x1, y1, x2, y2, "conso2_P", "transparent", 1); break;
}
}
else if(this->typeCourbe == COURBE_LIGNE)
{
if(i!= 23)
{
switch(plage[i])
{
case 1: drawer->DrawLine(lx + pasX/2 + i*pasX, ly - coorX_conso[i], lx + pasX/2 + (i+1)*pasX, ly - coorX_conso[i+1], "conso2_HC"); break;
case 2: drawer->DrawLine(lx + pasX/2 + i*pasX, ly - coorX_conso[i], lx + pasX/2 + (i+1)*pasX, ly - coorX_conso[i+1], "conso2_HP"); break;
case 3: drawer->DrawLine(lx + pasX/2 + i*pasX, ly - coorX_conso[i], lx + pasX/2 + (i+1)*pasX, ly - coorX_conso[i+1], "conso2_P"); break;
}
}
// A ecrire 4 types point x 2 lignes de courbe (conso et react)
}
}
}
}
In order to simplify my code and avoid some test I just want to transform that :
switch(plage[i])
{
case 1: drawer->DrawFilledGradientRectangle(x1, y1, x2, y2, "conso_HC", "transparent", 1); break;
case 2: drawer->DrawFilledGradientRectangle(x1, y1, x2, y2, "conso_HP", "transparent", 1); break;
case 3: drawer->DrawFilledGradientRectangle(x1, y1, x2, y2, "conso_P", "transparent", 1); break;
}
Into that :
drawer->DrawFilledGradientRectangle(x1, y1, x2, y2, gradient[plage[i]], "transparent", 1);
So I rewrite this function like that :
void CourbeComptage::afficheCourbeJour_nonEDF(CWnd *cwnd)
{
static char gradient[4][9] = {"default", "conso_HC", "conso_HP", "conso_P"},
solid[4][10] = {"default", "conso2_HC", "conso2_HP", "conso2_P"};
dessin ligne,rectangle,texte;
int i;
int lx = x + margeH;
int ly = y + haut - margeV;
int x1, y1, x2, y2;
if(flagCourbe)
{
afficheGraduation();
// 4 - tracer la courbe de consommation avec des plages horaires
for(i=0;i<24;i++)
{
x1 = lx + i * pasX;
y1 = ly - coorX_conso[i];
x2 = lx + (i + 1) * pasX;
y2 = ly - 1;
plage[i] = (plage[i] > 3) ? 3 : (plage[i] < 1) ? 1 : plage[i];
if(typeCourbe == COURBE_BARRE_3D)
{
drawer->DrawFilledGradientRectangle(x1, y1, x2, y2, gradient[plage[i]], "transparent", 1);
}
else if(typeCourbe == COURBE_BARRE)
{
drawer->DrawFilledSolidRectangle(x1, y1, x2, y2, solid[plage[i]], "transparent", 1);
}
else if(this->typeCourbe == COURBE_LIGNE)
{
if(i!= 23)
{
drawer->DrawLine(lx + pasX/2 + i*pasX, ly - coorX_conso[i], lx + pasX/2 + (i+1)*pasX, ly - coorX_conso[i+1], solid[plage[i]]);
}
}
}
}
}
And that don't works, meaning that the DrawFilledSolidRectangle (for example) get the string, but it don't draw the rectangle following the color passed in the string.
I don't know why.
I tried to dinamically allocate the two tab gradient and solid but that don't works too.
Here are the prototypes of some functions :
void DrawLine(int x1, int y1, int x2, int y2, char * penName);
void DrawFilledSolidRectangle(int x1, int y1, int x2, int y2, char * colorName, char * borderPen, int borderSize = 1, bool ombre = false);
void DrawFilledGradientRectangle(int x1, int y1, int x2, int y2, char * gradientName, char * borderPen, int borderSize = 1, bool ombre = false);
And here is the code of the DrawFilledSolidRectangle (DrawFilledGradientRectangle is the same except the Brush that is used)
Rect * rects = (Rect *)malloc(borderSize * sizeof(Rect));
Rect * tmp;
int i;
if(ombre) DrawRectangle(x1, y1, x2, y2, borderPen, true);
for(i = 0 ; i < borderSize ; i++)
{
tmp = new Rect(x1+i, y1+i, x2-x1-i, y2-y1-i);
rects[i] = *tmp;
}
DrawRectangles(rects, borderSize, borderPen);
x1 += i;
y1 += i;
x2 -= x1+i;
y2 -= y1-i;
SolidBrush * b = new SolidBrush(couleurs[colorName]);
gNaa->FillRectangle(b, x1, y1, x2, y2);
delete[](rects);
Thanks for your help, and sorry for my english.

Using conditional expressions makes this very simple:
drawer->DrawFilledGradientRectangle(x1, y1, x2, y2, (plage[i] == 1 ? "conso_HC" : (plage[i] == 2 ? "conso_HP" : "conso_P")), "transparent", 1);

Related

Triangle rasterization DirectX & Win32 Gdi

I'm currently following Andre Lamothe's book Tricks of the Windows Game Programming Gurus and trying to write my own software renderer with Win32 GDI. However, I got stuck at the triangle rasterization part of the book where the author is using Bresenham's line algorithm. I managed to get the rasterization to work on DirectX, but not on Win32 GDI despite identical rendering code. Both renders a triangle but the DirectX one renders it correctly while the Win32 almost renders it correctly
Link to my code: https://pastebin.com/VwySmQXS
It could be worth mention that the DirectX version is written in c++, while my own is written in C. I wasn't able to get a good screenshot of the two triangles so here is a picture painted in paint of how they both look.
Left is DirectX (how I want it to look), right is Win32 GDI:
Am I missing something here? Both draw_triangle_2d are called with the same arguments.
static void draw_top_tri(struct render_buffer *buffer,
int x1, int y1,
int x2, int y2,
int x3, int y3,
float r, float g, float b, float a)
{
unsigned int color = vec4_to_uint(vec4_mul(Vec4(r, g, b, a), 255.0f));
// this function draws a triangle that has a flat top
float dx_right, // the dx/dy ratio of the right edge of line
dx_left, // the dx/dy ratio of the left edge of line
xs, xe, // the starting and ending points of the edges
height; // the height of the triangle
int temp_x, // used during sorting as temps
temp_y,
right, // used by clipping
left;
// destination address of next scanline
unsigned int *dest_addr = NULL;
// test order of x1 and x2
if(x2 < x1)
{
temp_x = x2;
x2 = x1;
x1 = temp_x;
} // end if swap
// compute delta's
height = (float)(y3 - y1);
dx_left = (x3 - x1) / height;
dx_right = (x3 - x2) / height;
// set starting points
xs = (float)x1;
xe = (float)x2 + (float)0.5;
// perform y clipping
if(y1 < MIN_CLIP_Y)
{
// compute new xs and ys
xs = xs + dx_left * (float)(-y1 + MIN_CLIP_Y);
xe = xe + dx_right * (float)(-y1 + MIN_CLIP_Y);
// reset y1
y1 = MIN_CLIP_Y;
} // end if top is off screen
if(y3 > MAX_CLIP_X)
y3 = MAX_CLIP_X;
// compute starting address in video memory
dest_addr = (unsigned int *)buffer->memory + y1 * buffer->width;
// test if x clipping is needed
if(x1 >= MIN_CLIP_X && x1 <= MAX_CLIP_X &&
x2 >= MIN_CLIP_X && x2 <= MAX_CLIP_X &&
x3 >= MIN_CLIP_X && x3 <= MAX_CLIP_X)
{
// draw the triangle
for(temp_y = y1; temp_y <= y3; temp_y++, dest_addr += buffer->width)
{
memset((unsigned int *)dest_addr + (unsigned int)xs,
color, (unsigned int)(xe - xs + 1) * 4);
// adjust starting point and ending point
xs += dx_left;
xe += dx_right;
} // end for
} // end if no x clipping needed
else
{
// clip x axis with slower version
// draw the triangle
for(temp_y = y1; temp_y <= y3; temp_y++, dest_addr += buffer->width)
{
// do x clip
left = (int)xs;
right = (int)xe;
// adjust starting point and ending point
xs += dx_left;
xe += dx_right;
// clip line
if(left < MIN_CLIP_X)
{
left = MIN_CLIP_X;
if(right < MIN_CLIP_X)
continue;
}
if(right > MAX_CLIP_X)
{
right = MAX_CLIP_X;
if(left > MAX_CLIP_X)
continue;
}
memset((unsigned int *)dest_addr + (unsigned int)left,
color, (unsigned int)(right - left + 1) * 4);
} // end for
} // end else x clipping needed
} // end Draw_Top_Tri
static void
draw_bottom_tri(struct render_buffer *buffer,
int x1, int y1,
int x2, int y2,
int x3, int y3,
float r, float g, float b, float a)
{
unsigned int color = vec4_to_uint(vec4_mul(Vec4(r, g, b, a), 255.0f));
// this function draws a triangle that has a flat bottom
float dx_right, // the dx/dy ratio of the right edge of line
dx_left, // the dx/dy ratio of the left edge of line
xs, xe, // the starting and ending points of the edges
height; // the height of the triangle
int temp_x, // used during sorting as temps
temp_y,
right, // used by clipping
left;
// destination address of next scanline
unsigned int *dest_addr;
// test order of x1 and x2
if(x3 < x2)
{
temp_x = x2;
x2 = x3;
x3 = temp_x;
} // end if swap
// compute delta's
height = (float)(y3 - y1);
dx_left = (x2 - x1) / height;
dx_right = (x3 - x1) / height;
// set starting points
xs = (float)x1;
xe = (float)x1; // +(float)0.5;
// perform y clipping
if(y1 < MIN_CLIP_Y)
{
// compute new xs and ys
xs = xs + dx_left * (float)(-y1 + MIN_CLIP_Y);
xe = xe + dx_right * (float)(-y1 + MIN_CLIP_Y);
// reset y1
y1 = MIN_CLIP_Y;
} // end if top is off screen
if(y3 > MAX_CLIP_X)
y3 = MAX_CLIP_X;
// compute starting address in video memory
dest_addr = (unsigned int *)buffer->memory + y1 * buffer->width;
// test if x clipping is needed
if(x1 >= MIN_CLIP_X && x1 <= MAX_CLIP_X &&
x2 >= MIN_CLIP_X && x2 <= MAX_CLIP_X &&
x3 >= MIN_CLIP_X && x3 <= MAX_CLIP_X)
{
// draw the triangle
for(temp_y = y1; temp_y <= y3; temp_y++, dest_addr += buffer->width)
{
memset((unsigned int *)dest_addr + (unsigned int)xs,
color, (unsigned int)(xe - xs + 1) * 4);
// adjust starting point and ending point
xs += dx_left;
xe += dx_right;
} // end for
} // end if no x clipping needed
else
{
// clip x axis with slower version
// draw the triangle
for(temp_y = y1; temp_y <= y3; temp_y++, dest_addr += buffer->width)
{
// do x clip
left = (int)xs;
right = (int)xe;
// adjust starting point and ending point
xs += dx_left;
xe += dx_right;
// clip line
if(left < MIN_CLIP_X)
{
left = MIN_CLIP_X;
if(right < MIN_CLIP_X)
continue;
}
if(right > MAX_CLIP_X)
{
right = MAX_CLIP_X;
if(left > MAX_CLIP_X)
continue;
}
memset((unsigned int *)dest_addr + (unsigned int)left,
color, (unsigned int)(right - left + 1) * 4);
} // end for
} // end else x clipping needed
} // end Draw_Bottom_Tri}
ENGINE_CORE_EXPORT void
draw_triangle_2d(struct render_buffer *buffer,
int x1, int y1,
int x2, int y2,
int x3, int y3,
float r, float g, float b, float a)
{
// this function draws a triangle on the destination buffer
// it decomposes all triangles into a pair of flat top, flat bottom
int temp_x, // used for sorting
temp_y,
new_x;
// test for h lines and v lines
if((x1 == x2 && x2 == x3) || (y1 == y2 && y2 == y3))
return;
// sort p1,p2,p3 in ascending y order
if(y2 < y1)
{
temp_x = x2;
temp_y = y2;
x2 = x1;
y2 = y1;
x1 = temp_x;
y1 = temp_y;
} // end if
// now we know that p1 and p2 are in order
if(y3 < y1)
{
temp_x = x3;
temp_y = y3;
x3 = x1;
y3 = y1;
x1 = temp_x;
y1 = temp_y;
} // end if
// finally test y3 against y2
if(y3 < y2)
{
temp_x = x3;
temp_y = y3;
x3 = x2;
y3 = y2;
x2 = temp_x;
y2 = temp_y;
} // end if
// do trivial rejection tests for clipping
if(y3 < MIN_CLIP_Y || y1 > MAX_CLIP_X ||
(x1 < MIN_CLIP_X && x2 < MIN_CLIP_X && x3 < MIN_CLIP_X) ||
(x1 > MAX_CLIP_X && x2 > MAX_CLIP_X && x3 > MAX_CLIP_X))
return;
// test if top of triangle is flat
if(y1 == y2)
{
draw_top_tri(buffer, x1, y1, x2, y2, x3, y3, r, g, b, a);
} // end if
else
if(y2 == y3)
{
draw_bottom_tri(buffer, x1, y1, x2, y2, x3, y3, r, g, b, a);
} // end if bottom is flat
else
{
// general triangle that's needs to be broken up along long edge
new_x = x1 + (int)(0.5 + (float)(y2 - y1) * (float)(x3 - x1) / (float)(y3 - y1));
// draw each sub-triangle
draw_bottom_tri(buffer, x1, y1, new_x, y2, x2, y2, r, g, b, a);
draw_top_tri(buffer, x2, y2, new_x, y2, x3, y3, r, g, b, a);
} // end else
} // end Draw_Triangle_2D

c++ triangle rasterization using edge detection

I am trying to implement triangle rasterization using this article as reference
https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/rasterization-stage
as such I have implemented an edge function with an input of 3 points. 2 defining a line and one as the point to be tested, annotated as p
bool SoftwareRendererImp::edgeFunction(float xa, float ya,
float xb, float yb,
float xp, float yp)
{
return ((xp - xa) * (yb - ya) - (yp - ya) * (xb - xa) >= 0);
}
in my rasterization function I am iterating over a set of integers ranging from the lowest to highest x and y values. This is to try and iterate over a box of best fit containing the triangle and test each point to see if it is contained in the triangle.
void SoftwareRendererImp::rasterize_triangle(float x0, float y0,
float x1, float y1,
float x2, float y2,
Color color)
{
// Task 3:
// Implement triangle rasterization
cout << "triangle----------------------------------------------------------------------------------------------------------------------- \n";
float minX = std::min(x0, x1);
minX = std::min(minX, x2);
float minY = std::min(y0, y1);
minY = std::min(minY, y2);
float maxX = std::max(x0, x1);
maxX = std::max(maxX, x2);
float maxY = std::max(y0, y1);
maxY = std::max(maxY, y2);
bool inside;
float px, py;
for (int x = minX; x < maxX; x++)
{
for (int y = minY; y < maxY; y++)
{
inside = true;
px = x + 0.5f;
py = y + 0.5f;
inside &= SoftwareRendererImp::edgeFunction(x0, y0, x1, y1, px, py);
inside &= SoftwareRendererImp::edgeFunction(x1, y1, x2, y2, px, py);
inside &= SoftwareRendererImp::edgeFunction(x2, y2, x0, y0, px, py);
if (inside)
{
SoftwareRendererImp::rasterize_point(x, y, color);
cout << "inside: " << x << ", " << y << "\n";
}
else
{
// cout << "outside: " << x << ", " << y << "\n";
}
}
}
}
From my understanding of the linked article this should work however it is not. Can anyone spot what it is that I am screwing up?
this expression was backwards
(xp - xa) * (yb - ya) - (yp - ya) * (xb - xa)
it should have been
(yp - ya) * (xb - xa) - (xp - xa) * (yb - ya)

How to pass variables from console

I'm writing a C++ graphic program. I need to translate, scale and rotate this rhombus shape (as well as other shapes). I want to write a function to do that but I've not figured out how to pass x1, y1, x2, y2 from the mouse inputs(or keyboard inputs) to the new transformation function I want to write.
I want to draw a shape on BGI screen, then click the 'translate' button, then enter some variables and the shape transforms.
FYI, I use BGI to do the graphics. Some shapes I draw with mouse inputs, some with keyboard inputs.
Here is my code:
void drawRhombus (int x1, int y1, int x2, int y2)
{
int x3 = x2 + (x2 - x1);
int y3 = y1;
int x4 = x2;
int y4 = y1 + (y1 - y2);
lineBresenham(x1, y1, x2, y2);
lineBresenham(x2, y2, x3, y3);
lineBresenham(x3, y3, x4, y4);
lineBresenham(x4, y4, x1, y1);
}
if (LOWORD(wParam) == 9) {
cout<<"Draw Rhombus"<<endl;
int x1, y1, x2, y2 = 0;
int count = 0;
coordinateLines();
while(1)
{
delay (0.0001);
if (ismouseclick(WM_LBUTTONDOWN))
{
getmouseclick(WM_LBUTTONDOWN, x1, y1);
cout<<"A("<<setXMachine2User(x1)<<","<<setYMachine2User(y1)<<")\n";
putpixel(x1,y1,color);
count++;
}
if (count == 1)
{
if (ismouseclick(WM_LBUTTONUP))
{
getmouseclick(WM_LBUTTONUP, x2, y2);
cout<<"B("<<setXMachine2User(x2)<<","<<setYMachine2User(y2)<<")\n";
drawRhombus(x1, y1, x2, y2);
cout<<"-------------------------------"<<endl;
count++;
}
}
if (count == 2)
{
count = 0;
}
}
}

C++ What's the standard way to define a recursive constructor?

Sorry, I edited my question now .Pay attention to the bold type words .
I really need a recursive constructor while defining a kdtree class .
But I'm afraid I'm not doing it the right way .
How can I do it more elegantly ?
This is my code using the this pointer ,it compiles and works well .
Don't do anything at all ,just showing the brief idea of what a recursive constructor should look like .
#include <iostream>
using namespace std;
class foo
{
public:
int a, b;
foo(unsigned int k)//this piece of code just shows the brief idea of what i'm trying to do.
{
if (k)
*this = foo(--k);
else
a = k, b = k;
}
};
int main()
{
foo f(3);
cout << f.a << f.b << endl;
getchar();
}
This is my kdtree sample code .This is what I'm actully trying to achieve ,still don't compile ,I'll edit it later.
class kdtree
{
public:
int16_t count;//数组里面可以只存mask和key生成的unique_key,因为树结构,和count可以后期生成
int16_t key;
int16_t mask;
inline bool is_full()
{
return mask + count == 0x8000;
};
shared_ptr<kdtree> left, right;
kdtree(){}
kdtree(int x1, int y1, int z1, int x2, int y2, int z2, int _x = 0, int _y = 0, int _z = 0, int len = 0, int ikey = 0x8000)
{
int i = 0x80 >> len / 3, j = 0x4000 >> len;
if ((x2 - x1)*(y2 - y1)*(z2 - z1) == j << 10)
{
count = j << 1;
key = ikey;
mask = ~ikey ^ (ikey - 1);
return;
}
switch (len++ % 3)
{
case 0:
if (x1 < _x&&x2 < _x)
{
*this = kdtree(x1, y1, z1, x2, y2, z2, _x, _y, _z, len, ikey -= j);
return;
}
if (x1 >= _x&&x2 >= _x)
{
*this = kdtree(x1, y1, z1, x2, y2, z2, _x + i, _y, _z, len, ikey += j);
return;
}
left = shared_ptr<kdtree>(new kdtree(x1, y1, z1, _x, y2, z2, _x, _y, _z, len, ikey -= j));
right = shared_ptr<kdtree>(new kdtree(_x, y1, z1, x2, y2, z2, _x + i, _y, _z, len, key += j));
count = j << 1;
key = ikey;
mask = ~ikey ^ (ikey - 1);
return;
case 1:
if (y1 < _y&&y2 < _y)
{
*this = kdtree(x1, y1, z1, x2, y2, z2, _x, _y, _z, len, ikey -= j);
return;
}
if (y1 >= _y&&y2 >= _y)
{
*this = kdtree(x1, y1, z1, x2, y2, z2, _x, _y + i, _z, len, ikey += j);
return;
}
left = shared_ptr<kdtree>(new kdtree(x1, y1, z1, x2, y2, z2, _x, _y, _z, len, ikey -= j));
right = shared_ptr<kdtree>(new kdtree(x1, y1, z1, x2, y2, z2, _x, _y + i, _z, len, ikey += j));
count = j << 1;
key = ikey;
mask = ~ikey ^ (ikey - 1);
return;
case 2:
if (x1 < _x&&x2 < _x)
{
*this = kdtree(x1, y1, z1, x2, y2, z2, _x, _y, _z, len, ikey);
return;
}
if (x1 >= _x&&x2 >= _x)
{
*this = kdtree(x1, y1, z1, x2, y2, z2, _x, _y, _z + i, len, ikey + j);
}
left = shared_ptr<kdtree>(new kdtree(x1, y1, z1, x2, y2, _z, _x, _y, _z, len, ikey));
right = shared_ptr<kdtree>(new kdtree(x1, y1, _z, x2, y2, z2, _x, _y, _z + i, len, ikey + j));
count = j << 1;
key = ikey;
mask = ~ikey ^ (ikey - 1);
return;
}
}
};
A constructor only builds one thing, so you can't use a constructor to build a group of things.
If you use new Class[ 20]; // 20 Classes get allocated, but each is constructed once in the constructor.
class Class
{
Class * left;
Class * right;
Class( SomeObject & x )
{
eatSomeData( x );
left = nullptr;
right = nullptr;
if (x->buildleft() )
left = new Class( x );
if (x->buildright() )
right = new Class( x );
}
};
At each call to the constructor, the constructor only deals with the object it is creating, the fact it is doing this recursively (based on the data in x), is sort of different. In this case the class is heavily bound into the tree, and can't be easily constructed without building a tree. Yes it is possible (from comments), but really really not advisable.
If you have a group of items you want to store (e.g. a tree), the typical building blocks are
Item - the thing (object) you store in the tree.
Node - an object which understands the tree, and how to traverse the tree.
TreeContainer - an object which holds the top of the tree, and which knows how to find stored Items
Builder - an object or function which takes your data and adds it into the tree by calling methods of the TreeContainer

Implementation of Line Drawing Algorithm doesn't work properly

First question, I have tried to calculate the expression, di+1=di+2*Δy−2*Δx(yi+1−yi) for the four quadrants. Irrespective of the quadrant, the expression was found to be the same, including signs.
Am I right, or, there has been some mistakes in my calculations (hence, I am wrong)?
Second question, if this expression is only applicable for the first octet, how can I apply this to other octets? To me, there is no way to determine which octet I am working on. Coz, the value of m always represent two opposite octets. For example, if 0<m<1, it represents 1st and 5th octet. Right?
Thirdly, how can we determine the initial/starting value of di?
#include <iostream>
#include "utils.h"
void BresenhamLine(double x1, double y1, double x2, double y2, int color)
{
if(x1>x2 || y1>y2)
{
Swap(x1, x2);
Swap(y1, y2);
}
double x = x1;
double y = y1;
double dx = x2 - x1;
double dy = y2 - y1;
double dt = 2 * (dy - dx);
double ds = 2 * dy;
double d = 2*dy - dx;
PlotPixel(x, y, color);
if(dx>=dy)
{
while(x<=x2)
{
x++;
if(d<0)
{
d = d + ds;
}
else
{
y++;
d = d + dt;
}
PlotPixel(x, y, color);
}
}
else
{
while(y<=y2)
{
y++;
if(d<0)
{
x++;
d = d + dt;
}
else
{
d = d + ds;
}
PlotPixel(x, y, color);
}
}
}
int main()
{
int gm = DETECT;
int gd = DETECT;
initgraph(&gm, &gd, "");
double x1 = 0;
double y1 = 0;
double r = 50;
double x2 = 0;
double y2 = 0;
double signx = 0;
double signy = 0;
for(int theta=0 ; theta<=360 ; theta++)
{
x2 = r * cos(DegreeToRad((double) theta));
y2 = r * sin(DegreeToRad((double) theta));
x1 = 5 * cos(DegreeToRad((double) theta));
y1 = 5 * sin(DegreeToRad((double) theta));
BresenhamLine(x1, y1, x2, y2, YELLOW);
}
getch();
closegraph();
return 0;
}
The lines that go through 2nd and 4th quadrant are not showing up.
How to fix that with some minor changes in my code?
With this input: x1: 100 y1: -100 x2: -100 y2: 100
this logic:
if(x1>x2 || y1>y2)
{
Swap(x1, x2);
Swap(y1, y2);
}
fails.
This page is a good place to start. It shows code as well for 1 of the octants:
http://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html
I think you need to swap the x if x1 > x2 and swap the y if y1 > y2 but not swap both if only 1 of those is true.
The external links section of the Wikipedia page contains several links to ready-made implementations that you can study.
Try this:
void BresenhamLine( double x1, double y1, double x2, double y2, int color )
{
const bool steep = (std::abs(y2 - y1) > std::abs(x2 - x1));
if(steep)
{
std::swap(x1, y1);
std::swap(x2, y2);
}
if(x1 > x2)
{
std::swap(x1, x2);
std::swap(y1, y2);
}
double dx = x2 - x1;
double dy = std::abs(y2 - y1);
double error = dx / 2;
int ystep = (y1 < y2) ? 1 : -1;
int y = (int)y1;
int maxX = (int)x2;
for(int x=(int)x1; x<maxX; x++)
{
if(steep)
{
PlotPixel(y, x, color);
}
else
{
PlotPixel(x, y, color);
}
error -= dy;
if(error < 0)
{
y += ystep;
error += dx;
}
}
}
I got this by slightly modifying the code here:http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#C.2B.2B