.NET Forum / Languages / C# / October 2007
C#- coordinate system, drawing
|
|
Thread rating:  |
Petra Rohmer - 23 Oct 2007 22:45 GMT 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
Peter Duniho - 23 Oct 2007 23:12 GMT > [...] > The points I needed as crosses, as text P1 [quoted text clipped - 11 lines] > 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
Petra Rohmer - 24 Oct 2007 06:19 GMT Hello,
>> [...] >> The points I needed as crosses, as text P1 [quoted text clipped - 14 lines] > 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
Peter Duniho - 24 Oct 2007 08:35 GMT > [...] > 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
Thomas Bauer - 24 Oct 2007 10:02 GMT 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
Fred Mellender - 24 Oct 2007 11:35 GMT I have programmed a similar application, including the traveling salesman algorithm. You can find it at http://www.frontiernet.net/~fredm/dps/Contents.htm Chapter 9. The source code can be downloaded from the same site.
> Hello, > [quoted text clipped - 24 lines] > > Regards Thomas Peter Duniho - 24 Oct 2007 18:54 GMT > [...] > Step1 is finished. [quoted text clipped - 5 lines] > > 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
Thomas Bauer - 24 Oct 2007 23:07 GMT 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) --------------------------------------
|....................................| |....................................| [quoted text clipped - 4 lines] |....................................| |....................................| --------------------------------------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
Peter Duniho - 25 Oct 2007 00:18 GMT > 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. [quoted text clipped - 3 lines] > 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#? > [quoted text clipped - 11 lines] > > 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. [quoted text clipped - 5 lines] > 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
Thomas Bauer - 26 Oct 2007 12:15 GMT 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 ); } } }
Peter Duniho - 26 Oct 2007 17:58 GMT > 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
 Signature I'm trying a new usenet client for Mac, Nemo OS X. You can download it at http://www.malcom-mac.com/nemo
Thomas Bauer - 26 Oct 2007 21:32 GMT 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. 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
Peter Duniho - 26 Oct 2007 21:48 GMT > 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
 Signature I'm trying a new usenet client for Mac, Nemo OS X. You can download it at http://www.malcom-mac.com/nemo
Thomas Bauer - 26 Oct 2007 21:58 GMT Hello Pete,
> ptCur.X = code.X; > ptCur.Y = code.Y; [quoted text clipped - 4 lines] > 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); } } }
Peter Duniho - 26 Oct 2007 22:36 GMT > 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
 Signature I'm trying a new usenet client for Mac, Nemo OS X. You can download it at http://www.malcom-mac.com/nemo
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|