C#- coordinate system, drawing

P

Petra Rohmer

Hello,

I want to ake following


0,0 (900mm,900mm)
--------------------------------------
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
--------------------------------------0,0(900mm,900mm)

Zeropoint should be definwe
legt,right (top or bottom)

The points I needed as crosses, as text P1

List
Point X,Y,

1, 10,10
2, 20,20
3, 30,40
4, 70,42
.......
.......


a) how can I make that?
b) how can I draw the panel with points and text?

Have you a example?

Best regards, Petra
 
P

Peter Duniho

Petra said:
[...]
The points I needed as crosses, as text P1

List
Point X,Y,

1, 10,10
2, 20,20
3, 30,40
4, 70,42
.......
.......


a) how can I make that?
b) how can I draw the panel with points and text?

In what context do you want to draw this? Should it be a new Control
class? Do you just want to draw into a Form?

Generally speaking, you draw either handling the Paint method for a
Control instance (which can be a control contained by a form or a form
itself), or you implement a class that inherits Control and in which you
override the OnPaint method (this is particularly convenient for drawing
into forms, since you're usually creating a new derived class anyway).

In the Paint method, you can get a Graphics instance from the
PaintEventArgs parameter and use that instance to draw. The Graphics
class has a variety of methods on it useful for drawing, including
DrawLine, DrawLines, FillRectangle, FillEllipse, and DrawString (to name
a few that could be useful for what you're describing).

As far as the coordinate system goes, by default the coordinate system
has the origin at the top-left of the Control's client area. However,
you can change this by creating a transformation matrix and applying it
to the Graphics instance before drawing (see the Matrix class and the
Graphics.Transform property). Using this, you can do a variety of
things, including moving the origin to any other position and changing
the direction of the axes.

Of course, in many cases it suffices to simply take into account the
default coordinate system and apply whatever conversion you might need
explicitly.

You should take a look at the MSDN docs for the above and try to
implement what you need. Once you've done so, if you have more specific
questions, please feel free to ask those as well.

Pete
 
P

Petra Rohmer

Hello,
[...]
The points I needed as crosses, as text P1

List
Point X,Y,

1, 10,10
2, 20,20
3, 30,40
4, 70,42
.......
.......


a) how can I make that?
b) how can I draw the panel with points and text?

In what context do you want to draw this? Should it be a new Control
class? Do you just want to draw into a Form?
yes into a form.
if working, the next step is I want to implement the shortest way.
I can arrive every point.
Example 1 to 4 is possible
2 to 4 is alo possible.

Do you have a example?


Regards Petra
 
P

Peter Duniho

Petra said:
[...]
if working, the next step is I want to implement the shortest way.
I can arrive every point.
Example 1 to 4 is possible
2 to 4 is alo possible.

I don't understand what you mean. What does "arrive every point" mean?
By "shortest way", do you mean the least amount of code? The fastest
code? Doing the least amount of actual programming yourself? Some sort
of calculation related to your data?

There are too many possible interpretations of what you wrote for me to
be able to figure it out. Please be more specific (and if possible,
perhaps get someone to help you with the translation...I try not to
hassle people about their English skills, but in this case it seems to
be creating a genuine communication barrier).

Pete
 
T

Thomas Bauer

Hello,

I want to help.

As the first the coordinate system must be drawn in a Form.
For example inside a panel from the toolbox.


After it the points with cross should be drawn.

List with n items. (x,y - positions)

P1 +

P2+
P3+ P4+


The zero can be in all corners.

Step1 is finished.


Step2 calc -> Event with a button

I must score all reaches points. (shortest way) Travel sale algorithm
everyone scores points can be reached directly.

draw the way.

Regards Thomas
 
P

Peter Duniho

Thomas said:
[...]
Step1 is finished.


Step2 calc -> Event with a button

I must score all reaches points. (shortest way) Travel sale algorithm
everyone scores points can be reached directly.

draw the way.

Are you Petra? I'm a bit confused regarding whether you're the original
person who posted, or someone else. Your post seems to imply you're the
same person, but the name is completely different.

Assuming you're the same person, here's what I understand:

You have figured out how to draw the data, and now only need to
implement some version of an algorithm to solve the traveling salesman
problem (noting, of course, that there's no perfect algorithmic solution
that problem). I assume that once you've calculated the route you're
interested in, drawing that route won't be a problem since you've
already figure out how to draw the original data itself.

As far as the algorithm itself goes, I hope that Fred's solution is
suitable for your needs. Not being a C# or .NET question, if it's not
you may want to do more research on your own with respect to that actual
algorithm, or find a newsgroup or other forum that is more specifically
dedicated to algorithm design outside the context of a specific language
or framework.

Pete
 
T

Thomas Bauer

Hello Peter,
Are you Petra? I'm a bit confused regarding whether you're the original
person who posted, or someone else. Your post seems to imply you're the
same person, but the name is completely different.
No, Im the collegue from Petra.
Assuming you're the same person, here's what I understand:

You have figured out how to draw the data, and now only need to
implement some version of an algorithm to solve the traveling salesman
problem (noting, of course, that there's no perfect algorithmic solution
that problem).
No first problem is, how can we figured only the List of coordinates
with or in C#?
The best is the user see like that.
-> So first we want to figured the positions.
+ P1
+P2

A cross and at the side the name of the point, how can we make that in
C#?
The coordinatesystem, how can we figured that in C#?

0,0 (900mm,900mm)
--------------------------------------
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
--------------------------------------0,0(900mm,900mm)

Zero point can be all corners.


We have a list with n items. (x and y positions)
For your information, it is a machine with x and y axis.
On the axles is is a table to moves the workpiece.
If on position must be marked something.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Second we want to know the shortest way.
We must start each position in order to reduce the cycle time of the
machine.

Regards Thomas & Petra
 
P

Peter Duniho

Thomas said:
No, Im the collegue from Petra.

Okay, thank you for the clarification. So we are at least talking about
the same instance of this problem. :)
No first problem is, how can we figured only the List of coordinates
with or in C#?

I am having trouble with the use of the word "figure". In English, the
word has multiple meanings, including "to calculate" (e.g. "to figure
something out") and "a drawing or schematic" (e.g. "a figure eight").

It might be helpful if you can use a different word, one that has a more
precise meaning in English and which still means the same thing as you
intend.

That said...
The best is the user see like that.
-> So first we want to figured the positions.
+ P1
+P2

A cross and at the side the name of the point, how can we make that in
C#?

I'm going to assume that by "how can we make that", you are asking what
code can be written to actually draw the cross marking the point and the
label.

There are at least a couple of ways to _draw_ the cross and the name of
the point. The easiest would be to just use Graphics.DrawString() and
use a string that includes the plus symbol and the name of the point.
For example:

int ipointCur; // the current point index
string strPoint = "+ P" + ipointCur;

Then draw the string with Graphics.DrawString() at the appropriate place.

That has the drawback that you can't accurately position the plus
symbol. You can get it close, but if you need exactly accurate
rendition of the point, you'll need something that draws the cross
explicitly. You can do this using the Graphics.DrawLine() method. For
example:

Graphics gfx; // the Graphics instance; for example, taken from
PaintEventArgs
Point[] rgpt; // some array of points
int ipointCur;
Point ptCur = rgpt[ipointCur];
string strPoint = "P" + ipointCur;

// These two lines of code draw the cross
gfx.DrawLine(Pens.Black, ptCur.X - 5, ptCur.Y, ptCur.X + 5, ptCur.Y);
gfx.DrawLine(Pens.Black, ptCur.X, ptCur.Y - 5, ptCur.X, ptCur.Y + 5);

// This block of code draws the label for the point
using (Brush brush = new SolidBrush(ForeColor))
{
gfx.DrawString(strPoint, Font, brush, ptCur.X + 10, ptCur.Y);
}
The coordinatesystem, how can we figured that in C#?

0,0 (900mm,900mm)
--------------------------------------
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
|....................................|
--------------------------------------0,0(900mm,900mm)

Zero point can be all corners.

Again, are you asking how to draw a representation of the coordinate
system? How to exactly depends on what you want it to look like. But
at the most basic, you can just draw the lines defining the intervals of
the coordinate system. You'd use Graphics.DrawLine() for this as well,
but iterating over the range of the intervals you want to draw.

There are some details you'd have to address, related to translating the
coordinate system used for your machine to that used in the form. But
that should not be difficult. It's a simple matter of scaling the input
(which from your post appears to be in millimeters) to screen
coordinates (which by default are pixels).

What I would do is make a custom control that does all of this. It
would use its own ClientRectangle property to determine where to draw
the grid for the coordinate system. You would either always draw in
pixels, converting from the original millimeters each time you need to
specify a point, or you could (as I suggested earlier) set the
transformation of the Graphics object being used to draw so that it does
this conversion for you.

As an example of the latter, consider this code:

void MapMillimetersToPixels(Graphics gfx, Rectangle rectPixels,
Rectangle rectMm)
{
Matrix matrix = new Matrix();
float scaleX, scaleY;

scaleX = (float)rectPixels.Width / rectMm.Width;
scaleY = (float)rectPixels.Height / rectMm.Height;
matrix.Scale(scaleX, scaleY);
matrix.Translate(rectPixels.Left - scaleX * rectMm.Left,
rectPixels.Top - scaleY * rectMm.Top);

gfx.Transform = matrix;
}

That will set the transform for the Graphics instance so that you can
draw using the coordinate system defined by the rectMm rectangle in
millimeters, and that coordinate system will get mapped to the on-screen
rectangle defined by rectPixels (in pixels, of course).

Note that the Rectangle struct does not require the Left to be less than
or equal to the Right, nor the Top less than or equal to the Bottom. So
you would simply set the rectMm struct as appropriate to deal with some
sort of mapping that requires reversal of the coordinate system (as in
the case where your origin for the input coordinate system is in the
lower-right for example).
We have a list with n items. (x and y positions)
For your information, it is a machine with x and y axis.
On the axles is is a table to moves the workpiece.
If on position must be marked something.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Second we want to know the shortest way.
We must start each position in order to reduce the cycle time of the
machine.

Sounds like traveling salesman to me. As I mentioned, hopefully Fred's
reply helps with that second part of the problem.

Pete
 
T

Thomas Bauer

Hello,
Hello Peter,

I advance now.
But with the transformation, I have problems.
And also with the zeropoint.

I need a function like this

SetZeropoint (Left_Bottom)
SetZeropoint (Left_Top)
SetZeropoint (Right_Bottom)
SetZeropoint (Right_Top)

Perhaps you help me again.

SetDimensionin_MM(0,0,900,900)
or
SetDimensionin_MM(0,0,400,200)

I use a normal Windows Form Application and insert a panel.

private System.Windows.Forms.Panel panel_draw;

The boardnumber I need in a smal red color. How can I make it?

Regards Thomas
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The code is
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Drawing.Drawing2D;

namespace Grafik
{
public partial class Form1 : Form
{
public List<CODES> ListCodes;

public class CODES
{
private double x;
private double y;

private int boardNumber;

public double X
{
get { return x; }
set { x = value; }
}

public double Y
{
get { return y; }
set { y = value; }
}

public int BoardNumber
{
get { return boardNumber; }
set { boardNumber = value; }
}

public void Init( )
{
X = 0;
Y = 0;
boardNumber = 0;
}
}

public Form1( )
{
InitializeComponent();
}

private void Form1_Load( object sender, EventArgs e )
{
ListCodes = new List<CODES>();
CODES obj;

int boardnumber = 0;
for ( int j = 0; j < 4; j++ )
{
for ( int i = 0; i < 5; i++ )
{
boardnumber++;
obj = new CODES();
obj.Init();
obj.X = obj.X + (j * 30);
obj.Y = obj.Y + (i * 15);
obj.BoardNumber = boardnumber;
ListCodes.Add( obj );
}
}
}

float ScaleX, ScaleY;

private void MapMillimetersToPixels( Graphics gfx, Rectangle
rectPixels, Rectangle rectMm )
{
Matrix matrix = new Matrix();
ScaleX = (float)rectPixels.Width / rectMm.Width;
ScaleY = (float)rectPixels.Height / rectMm.Height;
matrix.Scale( ScaleX, ScaleY );
matrix.Translate( rectPixels.Left - ScaleX * rectMm.Left,
rectPixels.Top - ScaleY * rectMm.Top );

gfx.Transform = matrix;
}

private int MillimetersToPixels_X( double value )
{
return Convert.ToInt32(ScaleX * value);
}

private int MillimetersToPixels_Y( double value )
{
return Convert.ToInt32(ScaleY * value);
}

public void DrawPanel( List<CODES> listCodes, PaintEventArgs e )
{
Graphics gfx; // the Graphics instance; for example, taken from
PaintEventArgs
gfx = e.Graphics;

Rectangle rectMM = new Rectangle( 0, 0, 400, 200 );
Rectangle rectPixel = new Rectangle( 0, 0, 490, 490 );

rectPixel = panel_draw.DisplayRectangle;
MapMillimetersToPixels( gfx, rectPixel, rectMM );

// panel_draw.RectangleToClient( rectPixel );

//MapMillimetersToPixels( gfx, rectPixel, rectMM );

// gfx.DrawRectangle( Pens.Red, 0, 0,
MillimetersToPixels_X( 200 ), MillimetersToPixels_Y( 77 ) );
// gfx.DrawRectangle( Pens.Red, 5, 5, MillimetersToPixels_X( 200 ),
MillimetersToPixels_Y(77) );

//Point[] rgpt; // some array of points
//rgpt = new Point[20];
//int ipointCur = 0;
Point ptCur; // = rgpt[ipointCur];
string strPoint;// = "P" + ipointCur;

//for ( int j = 0; j < 20; j++ )
//{
// rgpt[j].X = 50;
// rgpt[j].Y = (j*6 ) + 20;
//}

ptCur = new Point();
foreach ( CODES code in listCodes )
{
ptCur.X = MillimetersToPixels_Y(code.X);
ptCur.Y = MillimetersToPixels_Y(code.Y);

// These two lines of code draw the cross
gfx.DrawLine( Pens.Black, ptCur.X - 5, ptCur.Y, ptCur.X + 5,
ptCur.Y );
gfx.DrawLine( Pens.Black, ptCur.X, ptCur.Y - 5, ptCur.X,
ptCur.Y + 5 );

// This block of code draws the label for the point
using ( Brush brush = new SolidBrush( ForeColor ) )
{
strPoint = "P" + code.BoardNumber + "(" + code.X +"," +
code.Y + ")";
gfx.DrawString( strPoint, Font, brush, ptCur.X + 10,
ptCur.Y );
}
}
//rectPixel = panel_draw.DisplayRectangle;
//MapMillimetersToPixels( gfx, rectPixel, rectMM );

}

private void panel_draw_Paint( object sender, PaintEventArgs e )
{
DrawPanel( ListCodes, e );
}
}
}
 
P

Peter Duniho

Hello,
Hello Peter,
I advance now.
But with the transformation, I have problems.
And also with the zeropoint.

I haven't had time to actually try your code. But my first read
through it, the one thing that stands out is that you are explicitly
converting the points in MM to pixels before drawing, in _addition_ to
calling MapMillimetersToPixels(). The point of the
MapMillimetersToPixels() method is to avoid having to do that. Once
you've called MapMillimetersToPixels(), you now have set the Graphics
instance up so that you can use millimeters as your coordinates for
drawing and it should just work.

One thing I'll point out: setting up that transformation will have the
effect of scaling how things are drawn, not just where they are drawn.
So, the lines for your crosses, and the text for the labels, those
will all be scaled accordingly. One way around that would be to
ensure that you use a specific Pen and Font size that is determined
according to the scale factor calculated. That is, if the scale winds
up being 0.75, and you'd normally want a Font that's 12 pt, you can
create a new Font that's actually 12 / 0.75 (or, in this example, 16
pt) so that when it gets scaled it's still the right size.

Alternatively, you could just scale things explicitly rather than
setting the transform for the Graphics instance. This makes drawing a
little less convenient with respect to placing things (you have to
scale all of your coordinates, but then you've already written the
code to do that :) ), but it does allow you to ensure that the
on-screen rendered objects are always the correct size you intend them
to be.

Pete
 
T

Thomas Bauer

Hello Peter,
I haven't had time to actually try your code.

ok, I must enter everything in mm.
Afterwards I call the function.
private void MapMillimetersToPixels( Graphics gfx, Rectangle
rectPixels, Rectangle rectMm )


I would like to draw it into the windows panel.
How I can do that?
Then I need the coordinates of the panel.
rectPixel = panel_draw.DisplayRectangle; - Is that correct?


Best regards Thomas
 
P

Peter Duniho

ok, I must enter everything in mm.
Afterwards I call the function.
private void MapMillimetersToPixels( Graphics gfx,
RectanglerectPixels, Rectangle rectMm )
I would like to draw it into the windows panel.
How I can do that?
Then I need the coordinates of the panel.
rectPixel = panel_draw.DisplayRectangle; - Is that correct?

Yes.

As a first attempt, based on the code you posted, you should try
simply replacing these two lines:

ptCur.X = MillimetersToPixels_Y(code.X);
ptCur.Y = MillimetersToPixels_Y(code.Y);

with these two:

ptCur.X = code.X;
ptCur.Y = code.Y;

In other words, just draw using millimeters as your coordinates.

Try that, see what happens. If it doesn't turn out closer to what
you're expecting, then if I have some time I'll look more closely at
it.

Pete
 
T

Thomas Bauer

Hello Pete,
ptCur.X = code.X;
ptCur.Y = code.Y;

In other words, just draw using millimeters as your coordinates.

Try that, see what happens. If it doesn't turn out closer to what
you're expecting, then if I have some time I'll look more closely at
it.
looks much more better, but not perfect.
The relationship is not correct.
The paneldraw to customer coordinates
Rectangle rectMM = new Rectangle( 0, 0, 900, 900 ); ???
rectPixel = panel_draw.DisplayRectangle; ???

Thanks for your support.

Regards Thomas



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Drawing.Drawing2D;

namespace Grafik
{
public partial class Form1 : Form
{
public List<CODES> ListCodes;

public class CODES
{
private double x;
private double y;

private int boardNumber;

public double X
{
get { return x; }
set { x = value; }
}

public double Y
{
get { return y; }
set { y = value; }
}

public int BoardNumber
{
get { return boardNumber; }
set { boardNumber = value; }
}

public void Init()
{
X = 0;
Y = 0;
boardNumber = 0;
}
}

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
ListCodes = new List<CODES>();
CODES obj;

int boardnumber = 0;
for (int j = 0; j < 4; j++)
{
for (int i = 0; i < 5; i++)
{
boardnumber++;
obj = new CODES();
obj.Init();
obj.X = obj.X + (j * 150);
obj.Y = obj.Y + (i * 70);
obj.BoardNumber = boardnumber;
ListCodes.Add(obj);
}
}
}

float ScaleX, ScaleY;

private void MapMillimetersToPixels(Graphics gfx, Rectangle
rectPixels, Rectangle rectMm)
{
Matrix matrix = new Matrix();
ScaleX = (float)rectPixels.Width / rectMm.Width;
ScaleY = (float)rectPixels.Height / rectMm.Height;
matrix.Scale(ScaleX, ScaleY);
matrix.Translate(rectPixels.Left - ScaleX * rectMm.Left,
rectPixels.Top - ScaleY * rectMm.Top);

gfx.Transform = matrix;
}

private int MillimetersToPixels_X(double value)
{
return Convert.ToInt32(ScaleX * value);
}

private int MillimetersToPixels_Y(double value)
{
return Convert.ToInt32(ScaleY * value);
}

public void DrawPanel(List<CODES> listCodes, PaintEventArgs e)
{
Graphics gfx; // the Graphics instance; for example, taken from
PaintEventArgs
gfx = e.Graphics;

Rectangle rectMM = new Rectangle( 0, 0, 900, 900 );
Rectangle rectPixel = new Rectangle( 0, 0, 900, 900 );

PointF ptCur;
string strPoint;

ptCur = new PointF();
foreach ( CODES code in listCodes )
{
ptCur.X = MillimetersToPixels_Y(code.X);
ptCur.Y = MillimetersToPixels_Y(code.Y);
ptCur.X = (float)code.X;
ptCur.Y = (float)code.Y;

// These two lines of code draw the cross
gfx.DrawLine( Pens.Black, ptCur.X - 5, ptCur.Y, ptCur.X +
5,ptCur.Y );
gfx.DrawLine( Pens.Black, ptCur.X, ptCur.Y - 5,
ptCur.X,ptCur.Y + 5 );

// This block of code draws the label for the point
using ( Brush brush = new SolidBrush( ForeColor ) )
{
strPoint = "P" + code.BoardNumber + "(" + code.X +","
+code.Y + ")";
gfx.DrawString( strPoint, Font, brush, ptCur.X +
10,ptCur.Y );
}
}

rectPixel = panel_draw.DisplayRectangle;
// calculation is finished -- now tranformation from mm to pixel
MapMillimetersToPixels( gfx, rectPixel, rectMM );
gfx.DrawRectangle(Pens.Red, 5, 5, 200, 166);
}

private void panel_draw_Paint(object sender, PaintEventArgs e)
{
DrawPanel(ListCodes, e);
}
}
}
 
P

Peter Duniho

looks much more better, but not perfect.
The relationship is not correct.
The paneldraw to customer coordinates
Rectangle rectMM = new Rectangle( 0, 0, 900, 900 ); ???
rectPixel = panel_draw.DisplayRectangle; ???

I'm afraid you'll have to be more specific than that.

I do note that at the end of the drawing method, you call the Map...()
method again. This is wrong. If you want to restore the
transformation, you'll instead want to save the current transformation
before calling Map...() the first time, and then just set the
Graphics.Transform back to its original value to restore it.

Other than that, there's nothing obviously wrong with the code you
posted. If it's not producing exactly the output you want, you need
to be very specific about what you expect and what it does instead.

Pete
 

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