A One Pixel Long Line

M

Martijn Mulder

I try to define a line with the length of 1 unit (1 pixel) that is, in fact,
just a point on the screen. But when I draw it with a wide pen with the
appropriate StartCap and EndCap (Round), it will appear as a dot.

I can think of a way to define a 1-pixel long line but it is ugly and
clumsy.
I subtract .5 from the given pixel's X and Y coordinate for the first
System.Drawing.PointF structure, and add .5 to the other PointF stucture. It
seems to work (see the code below), but it doesn't feel good.

Is there a standard way to obtain a line with unit length 1?



//namespace OnePixelLine
namespace OnePixelLine
{


//class Form
class Form:System.Windows.Forms.Form
{


//one integer type point that won't produce output
System.Drawing.Point point0=new System.Drawing.Point(50,50);


//two integer type points that produce 2-pixels long line
System.Drawing.Point point1=new System.Drawing.Point(100,100);
System.Drawing.Point point2=new System.Drawing.Point(101,101);



//two float type points that produce 1-pixel long line, but it is ugly
System.Drawing.PointF pointf1=new System.Drawing.PointF(149.5f,149.5f);
System.Drawing.PointF pointf2=new System.Drawing.PointF(150.5f,150.5f);



//a pen
System.Drawing.Pen pen=new System.Drawing.Pen(System.Drawing.Color.Red);



//constructor
Form()
{

//widen pen. Remove this to check the length of the lines
pen.Width=9;


//set StartCap and EndCap both to Round
pen.StartCap=System.Drawing.Drawing2D.LineCap.Round;
pen.EndCap=System.Drawing.Drawing2D.LineCap.Round;


//prepare for paint
Paint+=new System.Windows.Forms.PaintEventHandler(OnPaint);
}




//OnPaint
void OnPaint(object a,System.Windows.Forms.PaintEventArgs b)
{

//this outputs nothing
b.Graphics.DrawLine(pen,point0,point0);


//this outputs a line 2 pixels long
b.Graphics.DrawLine(pen,point1,point2);


//this outputs a line 1 pixel long, but it is clumsy
b.Graphics.DrawLine(pen,pointf1,pointf2);
}



//Main
public static void Main()
{
System.Windows.Forms.Application.Run(new Form());
}
}
}
 
M

Michael C

Martijn Mulder said:
I try to define a line with the length of 1 unit (1 pixel) that is, in
fact,
just a point on the screen. But when I draw it with a wide pen with the
appropriate StartCap and EndCap (Round), it will appear as a dot.

I can think of a way to define a 1-pixel long line but it is ugly and
clumsy.
I subtract .5 from the given pixel's X and Y coordinate for the first
System.Drawing.PointF structure, and add .5 to the other PointF stucture.
It
seems to work (see the code below), but it doesn't feel good.

Is there a standard way to obtain a line with unit length 1?

Can't you just draw a pixel?
 
M

Martijn Mulder

Can't you just draw a pixel?

No, I need it as a line to do hit testing on it.

Or do you know a way to
1. to do a hit test on a pixel? (with a wide pen)
2. to draw an individual pixel?
 
M

Michael C

Martijn Mulder said:
No, I need it as a line to do hit testing on it.

Or do you know a way to
1. to do a hit test on a pixel? (with a wide pen)
2. to draw an individual pixel?

What do you mean by hittest? Is this a function in the framework or
something you've written?
 
M

Martijn Mulder

What do you mean by hittest? Is this a function in the framework or
something you've written?

With a hittest I mean finding out if the mouse cursor is over a given area
on the screen. It is within the framework, thanks heaven. Take a look at the
post called 'RE: Hit Detection on a Line' from 18-4-2006 8:28
 
M

Martijn Mulder

What do you mean by hittest? Is this a function in the framework or
With a hittest I mean finding out if the mouse cursor is over a given area
on the screen. It is within the framework, thanks heaven. Take a look at
the post called 'RE: Hit Detection on a Line' from 18-4-2006 8:28


Sorry, that is supposed to be 17-3-2006 17:03
 
M

Martijn Mulder

Can't you just draw a pixel?
No, I need it as a line to do hit testing on it.
Or do you know a way to
1. do a hit test on a pixel?
2. draw an individual pixel?

The individual pixel I want to 'hit' is not part of a line, as I initially
thought, but the sole inhabitant of a System.Drawing.Rectangle object, as in
the code below. See if you are man (or woman) enough to hit the pixel with
the mouse pointer :)



//namespace HitPixel
namespace HitPixel
{


//class Form
class Form:System.Windows.Forms.Form
{


//the pixel that we want to hit, the 'hitpixel'
System.Drawing.Point point=new System.Drawing.Point(150,150);


//line 1, arrowshaped, pointing towards 'hitpixel'
System.Drawing.Point point1=new System.Drawing.Point(150,50);
System.Drawing.Point point2=new System.Drawing.Point(150,140);


//line 2, arrowshaped, pointing towards 'hitpixel'
System.Drawing.Point point3=new System.Drawing.Point(150,250);
System.Drawing.Point point4=new System.Drawing.Point(150,160);


//line 3, arrowshaped, pointing towards 'hitpixel'
System.Drawing.Point point5=new System.Drawing.Point(50,150);
System.Drawing.Point point6=new System.Drawing.Point(140,150);


//line 4, arrowshaped, pointing towards 'hitpixel'
System.Drawing.Point point7=new System.Drawing.Point(250,150);
System.Drawing.Point point8=new System.Drawing.Point(160,150);


//the graphicspath. Holds nothing more than the 'hitpixel'
System.Drawing.Drawing2D.GraphicsPath graphicspath=new
System.Drawing.Drawing2D.GraphicsPath();


//a Black pen
System.Drawing.Pen blackpen=new
System.Drawing.Pen(System.Drawing.Color.Black,20);


//a Red pen
System.Drawing.Pen redpen=new
System.Drawing.Pen(System.Drawing.Color.Red,20);


//a pen
System.Drawing.Pen pen;



//constructor
Form()
{

//set style for double buffered graphics
SetStyle
(
System.Windows.Forms.ControlStyles.AllPaintingInWmPaint|
System.Windows.Forms.ControlStyles.DoubleBuffer|
System.Windows.Forms.ControlStyles.ResizeRedraw|
System.Windows.Forms.ControlStyles.UserPaint,
true
);


//set EndCaps of both pens to ArrowAnchor
blackpen.EndCap=System.Drawing.Drawing2D.LineCap.ArrowAnchor;
redpen.EndCap=System.Drawing.Drawing2D.LineCap.ArrowAnchor;


//set pen
pen=blackpen;


//add Rectangle to graphicspath. Rectangle is 1x1 pixel
graphicspath.AddRectangle
(
new System.Drawing.Rectangle
(
point.X,
point.Y,
1,
1
)
);


//prepare for mouse-input
MouseMove+=new System.Windows.Forms.MouseEventHandler(OnMouseMove);


//prepare for paint
Paint+=new System.Windows.Forms.PaintEventHandler(OnPaint);
}



//OnMouseMove
void OnMouseMove(object a,System.Windows.Forms.MouseEventArgs b)
{

//use Black pen
pen=blackpen;

if(graphicspath.IsOutlineVisible(b.X,b.Y,System.Drawing.Pens.Black))
{

//if pixel is hit, use Red pen
pen=redpen;
}

//force redraw
Invalidate();
}



//OnPaint
void OnPaint(object a,System.Windows.Forms.PaintEventArgs b)
{
b.Graphics.DrawLine(pen,point1,point2);
b.Graphics.DrawLine(pen,point3,point4);
b.Graphics.DrawLine(pen,point5,point6);
b.Graphics.DrawLine(pen,point7,point8);
b.Graphics.FillPath(System.Drawing.Brushes.Black,graphicspath);
}



//Main
public static void Main()
{
System.Windows.Forms.Application.Run(new Form());
}
}
}
 
M

Michael C

I didn't realise drawing a single pixel wasn't in the framework. You could
use the SetPixel and GetPixel API.

[DllImport("gdi32")]
private static extern int SetPixel(int hdc, int x, int y, int crColor);
[DllImport("gdi32")]
private static extern int GetPixel(int hdc, int x, int y);

I'm still a bit confused about what you want to do. Do you want to make the
pixel larger so it's easier to hit?

Michael
 
M

Michael C

Martijn Mulder said:
SetStyle
(
System.Windows.Forms.ControlStyles.AllPaintingInWmPaint|
System.Windows.Forms.ControlStyles.DoubleBuffer|
System.Windows.Forms.ControlStyles.ResizeRedraw|
System.Windows.Forms.ControlStyles.UserPaint,
true
);

Ever heard of the using statement? :)

Michael
 
M

Martijn Mulder

SetStyle
Ever heard of the using statement? :)

The using statement? Not using it makes it easier to look up different
classes since I know where they reside. I am an ardent typer :)
 
M

Michael C

Martijn Mulder said:
The using statement? Not using it makes it easier to look up different
classes since I know where they reside. I am an ardent typer :)

It would make everything else harder though, typing, reading, maintaining.
:)

Michael
 
M

Martijn Mulder

SetStyle
It would make everything else harder though, typing, reading, maintaining.
:)


I don't agree.

- Typing: My editor makes it very easy to copy a line. All editors do
- Reading: When a long name shows up (i.e. System.Drawing...,
System.Windows.Forms...) I know it is SDK-defined, all else is user defined.
The eye is wandering for repitition, for redundancy
- Maintaining: Maintaining code is a nightmare, any kind of code

Never using using (no, never!) makes the code self-documenting, so to speak.
Only thing is that I am new to C# so I start out typing javax.swing... when
I mean System.Drawing...
 
M

Michael C

Martijn Mulder said:
I don't agree.

- Typing: My editor makes it very easy to copy a line. All editors do

You can't disagree there. You type more than me, full stop.
- Reading: When a long name shows up (i.e. System.Drawing...,
System.Windows.Forms...) I know it is SDK-defined, all else is user
defined. The eye is wandering for repitition, for redundancy

You read more also. Personally I found your code much more difficult to
read. I know Point is in System.Drawing so don't need to be reminded over
and over. Besides, where it is isn't so important to me that I need see it
every time it is used.
- Maintaining: Maintaining code is a nightmare, any kind of code

That's a cop out. Some code is easier to maintain than other.
Never using using (no, never!) makes the code self-documenting, so to
speak. Only thing is that I am new to C# so I start out typing
javax.swing... when I mean System.Drawing...

I doubt you'll find many developers who agree :)

Michael
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top