drawline produces broken lines Topic is solved

 Earned a small fee
 Posts: 17
 Joined: Fri Oct 05, 2007 8:46 am
drawline produces broken lines
Some of the lines in my drawing are broken. Please see the file attached. Any solution to how to draw absolutely smooth lines would be greatly appreciated.
Thanks
Anand.
Thanks
Anand.
Wxwidgets 2.8.9
OS WindowsXP
IDE VS 2005
OS WindowsXP
IDE VS 2005

 Earned a small fee
 Posts: 17
 Joined: Fri Oct 05, 2007 8:46 am
It might be totally stupid what I am saying, but there is nothing broken with the lines. It seems you are drawing two lines over eachother, slightly mispositioned.
If you look at the top part you are drawing lines 10, 107 and 112. And at the bottom part, where it looks jagged you are drawing one line over the other you are drawing 17, 110, 113 and 111. So the only issue you have is antialiasing, there is nothing "broken" with line drawing here.
With regards,
 Jorgen
If you look at the top part you are drawing lines 10, 107 and 112. And at the bottom part, where it looks jagged you are drawing one line over the other you are drawing 17, 110, 113 and 111. So the only issue you have is antialiasing, there is nothing "broken" with line drawing here.
With regards,
 Jorgen
Forensic Software Engineer
Netherlands Forensic Insitute
http://english.forensischinstituut.nl/

Jorg's WasteBucket
http://www.xs4all.nl/~jorgb/wb
Netherlands Forensic Insitute
http://english.forensischinstituut.nl/

Jorg's WasteBucket
http://www.xs4all.nl/~jorgb/wb
I have found one example:
That's very interesting  I also use lines in my diagrams, so I'll try write wx function for this algorithm
Code: Select all
void AALine(int x0, int y0, int x1, int y1)
{
int addr = (y0*640+x0)*4;
int dx = x1x0;
int dy = y1y0;
/* By switching to (u,v), we combine all eight octants */
if (abs(dx) > abs(dy))
{
/* Note: If this were actual C, these integers would be lost
* at the closing brace. That's not what I mean to do. Do what
* I mean. */
int du = abs(dx);
int dv = abs(dy);
int u = x1;
int v = y1;
int uincr = 4;
int vincr = 640*4;
if (dx < 0) uincr = uincr;
if (dy < 0) vincr = vincr;
}
else
{
int du = abs(dy);
int dv = abs(dx);
int u = y1;
int v = x1;
int uincr = 640*4;
int vincr = 4;
if (dy < 0) uincr = uincr;
if (dx < 0) vincr = vincr;
}
int uend = u + 2 * du;
int d = (2 * dv)  du; /* Initial value as in Bresenham's */
int incrS = 2 * dv; /* Δd for straight increments */
int incrD = 2 * (dv  du); /* Δd for diagonal increments */
int twovdu = 0; /* Numerator of distance; starts at 0 */
double invD = 1.0 / (2.0*sqrt(du*du + dv*dv)); /* Precomputed inverse denominator */
double invD2du = 2.0 * (du*invD); /* Precomputed constant */
do
{
/* Note: this pseudocode doesn't ensure that the address is
* valid, or that it even represents a pixel on the same side of
* the screen as the adjacent pixel */
DrawPixelD(addr, twovdu*invD);
DrawPixelD(addr + vincr, invD2du  twovdu*invD);
DrawPixelD(addr  vincr, invD2du + twovdu*invD);
if (d < 0)
{
/* choose straight (u direction) */
twovdu = d + du;
d = d + incrS;
}
else
{
/* choose diagonal (u+v direction) */
twovdu = d  du;
d = d + incrD;
v = v+1;
addr = addr + vincr;
}
u = u+1;
addr = addr+uincr;
} while (u < uend);
}
It work
That's my implementation of Wu's algorithm for wxWidgets ( I have found code and adapt it to wx ), it's ugly but work fine:
That's my implementation of Wu's algorithm for wxWidgets ( I have found code and adapt it to wx ), it's ugly but work fine:
Code: Select all
/**********************************************************************************************/
void DrawWuLine( wxDC *pDC, short X0, short Y0, short X1, short Y1 )
{
unsigned short IntensityShift, ErrorAdj, ErrorAcc;
unsigned short ErrorAccTemp, Weighting, WeightingComplementMask;
short DeltaX, DeltaY, Temp, XDir;
/* Make sure the line runs top to bottom */
if (Y0 > Y1) {
Temp = Y0; Y0 = Y1; Y1 = Temp;
Temp = X0; X0 = X1; X1 = Temp;
}
/* Draw the initial pixel, which is always exactly intersected by
the line and so needs no weighting */
pDC>SetPen( *wxBLACK );
pDC>DrawPoint( X0, Y0 );
if ((DeltaX = X1  X0) >= 0) {
XDir = 1;
} else {
XDir = 1;
DeltaX = DeltaX; /* make DeltaX positive */
}
/* Specialcase horizontal, vertical, and diagonal lines, which
require no weighting because they go right through the center of
every pixel */
if ((DeltaY = Y1  Y0) == 0) {
/* Horizontal line */
while (DeltaX != 0) {
X0 += XDir;
pDC>DrawPoint( X0, Y0 );
}
return;
}
if (DeltaX == 0) {
/* Vertical line */
do {
Y0++;
pDC>DrawPoint( X0, Y0 );
} while (DeltaY != 0);
return;
}
if (DeltaX == DeltaY) {
/* Diagonal line */
do {
X0 += XDir;
Y0++;
pDC>DrawPoint( X0, Y0 );
} while (DeltaY != 0);
return;
}
/* Line is not horizontal, diagonal, or vertical */
ErrorAcc = 0; /* initialize the line error accumulator to 0 */
/* # of bits by which to shift ErrorAcc to get intensity level */
IntensityShift = 8;
/* Mask used to flip all bits in an intensity weighting, producing the
result (1  intensity weighting) */
WeightingComplementMask = 255;
/* Is this an Xmajor or Ymajor line? */
if (DeltaY > DeltaX) {
/* Ymajor line; calculate 16bit fixedpoint fractional part of a
pixel that X advances each time Y advances 1 pixel, truncating the
result so that we won't overrun the endpoint along the X axis */
ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY;
/* Draw all pixels other than the first and last */
while (DeltaY) {
ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
ErrorAcc += ErrorAdj; /* calculate error for next pixel */
if (ErrorAcc <= ErrorAccTemp) {
/* The error accumulator turned over, so advance the X coord */
X0 += XDir;
}
Y0++; /* Ymajor, so always advance Y */
/* The IntensityBits most significant bits of ErrorAcc give us the
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = ErrorAcc >> IntensityShift;
pDC>SetPen( wxColour( Weighting, Weighting, Weighting ) );
pDC>DrawPoint( X0, Y0 );
pDC>SetPen( wxColour( Weighting ^ WeightingComplementMask, Weighting ^ WeightingComplementMask, Weighting ^ WeightingComplementMask ) );
pDC>DrawPoint( X0 + XDir, Y0 );
}
/* Draw the final pixel, which is
always exactly intersected by the line
and so needs no weighting */
pDC>SetPen( *wxBLACK );
pDC>DrawPoint( X1, Y1 );
return;
}
/* It's an Xmajor line; calculate 16bit fixedpoint fractional part of a
pixel that Y advances each time X advances 1 pixel, truncating the
result to avoid overrunning the endpoint along the X axis */
ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX;
/* Draw all pixels other than the first and last */
while (DeltaX) {
ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
ErrorAcc += ErrorAdj; /* calculate error for next pixel */
if (ErrorAcc <= ErrorAccTemp) {
/* The error accumulator turned over, so advance the Y coord */
Y0++;
}
X0 += XDir; /* Xmajor, so always advance X */
/* The IntensityBits most significant bits of ErrorAcc give us the
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = ErrorAcc >> IntensityShift;
pDC>SetPen( wxColour( Weighting, Weighting, Weighting ) );
pDC>DrawPoint( X0, Y0 );
pDC>SetPen( wxColour( Weighting ^ WeightingComplementMask, Weighting ^ WeightingComplementMask, Weighting ^ WeightingComplementMask ) );
pDC>DrawPoint( X0, Y0 + 1 );
}
/* Draw the final pixel, which is always exactly intersected by the line
and so needs no weighting */
pDC>SetPen( *wxBLACK );
pDC>DrawPoint( X1, Y1 );
}
v2 for draw coloured line ( use Pen and Brush from DC )
Code: Select all
/**********************************************************************************************/
wxColour GetColorAverage( wxColour color1, wxColour color2, float weight)
{
unsigned char r, g, b;
r = (unsigned char)( 1.0 * color1.Red() * weight + 1.0 * color2.Red() * ( 1  weight) );
g = (unsigned char)( 1.0 * color1.Green() * weight + 1.0 * color2.Green() * ( 1  weight) );
b = (unsigned char)(1.0 * color1.Blue() * weight + 1.0 * color2.Blue() * ( 1  weight) );
return wxColour(r, g, b);
}
/**********************************************************************************************/
void DrawWuLine( wxDC *pDC, short X0, short Y0, short X1, short Y1 )
{
wxASSERT( pDC );
if( !pDC )
return;
wxColour cl = pDC>GetPen().GetColour();
wxColour clb = pDC>GetBrush().GetColour();
unsigned short IntensityShift, ErrorAdj, ErrorAcc;
unsigned short ErrorAccTemp, Weighting, WeightingComplementMask;
short DeltaX, DeltaY, Temp, XDir;
/* Make sure the line runs top to bottom */
if (Y0 > Y1) {
Temp = Y0; Y0 = Y1; Y1 = Temp;
Temp = X0; X0 = X1; X1 = Temp;
}
/* Draw the initial pixel, which is always exactly intersected by
the line and so needs no weighting */
pDC>SetPen( cl );
pDC>DrawPoint( X0, Y0 );
if ((DeltaX = X1  X0) >= 0) {
XDir = 1;
} else {
XDir = 1;
DeltaX = DeltaX; /* make DeltaX positive */
}
/* Specialcase horizontal, vertical, and diagonal lines, which
require no weighting because they go right through the center of
every pixel */
if ((DeltaY = Y1  Y0) == 0) {
/* Horizontal line */
while (DeltaX != 0) {
X0 += XDir;
pDC>DrawPoint( X0, Y0 );
}
return;
}
if (DeltaX == 0) {
/* Vertical line */
do {
Y0++;
pDC>DrawPoint( X0, Y0 );
} while (DeltaY != 0);
return;
}
if (DeltaX == DeltaY) {
/* Diagonal line */
do {
X0 += XDir;
Y0++;
pDC>DrawPoint( X0, Y0 );
} while (DeltaY != 0);
return;
}
/* Line is not horizontal, diagonal, or vertical */
ErrorAcc = 0; /* initialize the line error accumulator to 0 */
/* # of bits by which to shift ErrorAcc to get intensity level */
IntensityShift = 8;
/* Mask used to flip all bits in an intensity weighting, producing the
result (1  intensity weighting) */
WeightingComplementMask = 255;
/* Is this an Xmajor or Ymajor line? */
if (DeltaY > DeltaX) {
/* Ymajor line; calculate 16bit fixedpoint fractional part of a
pixel that X advances each time Y advances 1 pixel, truncating the
result so that we won't overrun the endpoint along the X axis */
ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY;
/* Draw all pixels other than the first and last */
while (DeltaY) {
ErrorAccTemp = ErrorAcc; /* remember current accumulated error */
ErrorAcc += ErrorAdj; /* calculate error for next pixel */
if (ErrorAcc <= ErrorAccTemp) {
/* The error accumulator turned over, so advance the X coord */
X0 += XDir;
}
Y0++; /* Ymajor, so always advance Y */
/* The IntensityBits most significant bits of ErrorAcc give us the
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = ErrorAcc >> IntensityShift;
wxColour cl2 = GetColorAverage( clb, cl, 1. * Weighting / 255 );
pDC>SetPen( cl2 );
pDC>DrawPoint( X0, Y0 );
cl2 = GetColorAverage( clb, cl, 1. * ( Weighting ^ WeightingComplementMask ) / 255 );
pDC>SetPen( cl2 );
pDC>DrawPoint( X0 + XDir, Y0 );
}
/* Draw the final pixel, which is
always exactly intersected by the line
and so needs no weighting */
pDC>SetPen( cl );
pDC>DrawPoint( X1, Y1 );
return;
}
/* It's an Xmajor line; calculate 16bit fixedpoint fractional part of a
pixel that Y advances each time X advances 1 pixel, truncating the
result to avoid overrunning the endpoint along the X axis */
ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX;
/* Draw all pixels other than the first and last */
while (DeltaX) {
ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
ErrorAcc += ErrorAdj; /* calculate error for next pixel */
if (ErrorAcc <= ErrorAccTemp) {
/* The error accumulator turned over, so advance the Y coord */
Y0++;
}
X0 += XDir; /* Xmajor, so always advance X */
/* The IntensityBits most significant bits of ErrorAcc give us the
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = ErrorAcc >> IntensityShift;
wxColour cl2 = GetColorAverage( clb, cl, 1. * Weighting / 255 );
pDC>SetPen( cl2 );
pDC>DrawPoint( X0, Y0 );
cl2 = GetColorAverage( clb, cl, 1. * ( Weighting ^ WeightingComplementMask ) / 255 );
pDC>SetPen( cl2 );
pDC>DrawPoint( X0, Y0 + 1 );
}
/* Draw the final pixel, which is always exactly intersected by the line
and so needs no weighting */
pDC>SetPen( cl );
pDC>DrawPoint( X1, Y1 );
}
Lester, this is very interesting stuff! Would you consider reposting that in the Code Dump under a new topic? It might help people looking for a line drawing routine.
Also, you might want to consider seeing if this can be integrated with wxWidgets itself. It would be a nice contribution to the original drawing algoritm
 Jorgen
Also, you might want to consider seeing if this can be integrated with wxWidgets itself. It would be a nice contribution to the original drawing algoritm
 Jorgen
Forensic Software Engineer
Netherlands Forensic Insitute
http://english.forensischinstituut.nl/

Jorg's WasteBucket
http://www.xs4all.nl/~jorgb/wb
Netherlands Forensic Insitute
http://english.forensischinstituut.nl/

Jorg's WasteBucket
http://www.xs4all.nl/~jorgb/wb
Sure, I'll be happy if it will help to somebodyJorg wrote:Lester, this is very interesting stuff! Would you consider reposting that in the Code Dump under a new topic? It might help people looking for a line drawing routine.
Also, you might want to consider seeing if this can be integrated with wxWidgets itself. It would be a nice contribution to the original drawing algoritm
 Jorgen
like tan already mentioned, wxWidgets supports antialiased drawing operations on all major platforms using wxGCGC.
Usually you only have to change/add 2 lines of code in your drawing routine.
Check the "drawing" sample.
http://forums.wxwidgets.org/viewtopic.php?p=66885#66885
Usually you only have to change/add 2 lines of code in your drawing routine.
Check the "drawing" sample.
http://forums.wxwidgets.org/viewtopic.php?p=66885#66885
Use the source, Luke!