Reputation: 6135
I have to represent graphically an oriented graph like in the image below.
alt text http://img694.imageshack.us/img694/1605/graf.gif
i have a C# form, when i click with the mouse on it i have to draw a node. If i click somewhere on the form where is not already a node drawn it means i cliked with the intetion of drawing a node, if it is a node there i must select it and memorize it. On the next mouse click if i touch a place where there is not already a node drawn it means like before that i want to draw a new node, if it is a node where i clicked i need to draw the line from the first memorized node to the selected one and add road cost details.
i know how to draw the circles that represent the nodes of the graph when i click on the form. i'm using the following code:
namespace RepGraficaAUnuiGraf
{
public partial class Form1 : Form
{
Graphics graphDrawingArea;
Bitmap bmpDrawingArea;
Graphics graph;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bmpDrawingArea = new Bitmap(Width, Height);
graphDrawingArea = Graphics.FromImage(bmpDrawingArea);
graph = Graphics.FromHwnd(this.Handle);
}
private void Form1_Click(object sender, EventArgs e)
{
DrawCentralCircle(((MouseEventArgs)e).X, ((MouseEventArgs)e).Y, 15);
graph.DrawImage(bmpDrawingArea, 0, 0);
}
void DrawCentralCircle(int CenterX, int CenterY, int Radius)
{
int start = CenterX - Radius;
int end = CenterY - Radius;
int diam = Radius * 2;
bmpDrawingArea = new Bitmap(Width, Height);
graphDrawingArea = Graphics.FromImage(bmpDrawingArea);
graphDrawingArea.DrawEllipse(new Pen(Color.Blue), start, end, diam, diam);
graphDrawingArea.DrawString("1", new Font("Tahoma", 13), Brushes.Black, new PointF(CenterX - 8, CenterY - 10));
}
}
}
My question is how can i find out if at the coordinates (x,y) on my form i drew a node and which one is it? I thought of representing the nodes as buttons, having a tag or something similar as the node number(which in drawing should be 1 for Santa Barbara, 2 for Barstow etc.)
Upvotes: 1
Views: 4623
Reputation: 11
You can also make a list of nodes and check if the distance between the center of the node to the clicked point is <= radius.
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
int x1 = node.Center.X, y1 = node.Center.Y, x2, y2;
Point local = this.PointToClient(Cursor.Position);
bool clicked = false;
x2 = local.X;
y2 = local.Y;
float distance = Convert.ToSingle(Math.Sqrt((x1 - x2) ^ 2 + (y1 - y2) ^ 2));
if(distance <= radius) clicked = true;
}
Upvotes: 1
Reputation: 2066
I'm afraid you're missing the basic intended pattern for Windows UIs. Throw out your code above and do this:
Create a data structure in memory that represents the "document" (everything you need to keep track of about the graph, its nodes and edges).
On mouse click, you don't draw. You just modify your "document" data structure (as suggested above). Plus you call Invalidate() which will cause a redraw later.
Override OnPaint(). That's where you do all your drawing, drawing your visual representation of the data structure you've stored.
Upvotes: 2
Reputation: 2618
Expanding upon the answer from Anders Abel:
When you click determine whether one of the nodes was hit
Upvotes: 4
Reputation: 17051
One way would be to create a UserControl that represents (and draws) your circles, and also handles when a user clicks it. You could then let each circle object determine whether or not it has been clicked rather than using X and Y coordinates to try to figure out where a user clicked and whether or not they clicked a circle.
Upvotes: 4
Reputation: 69260
A simple approach is to put all circles into a list when you draw them. In your mouse click handler you can go through the list and check for each of the circles whether the mouse is within the circle.
This approach won't however scale in the long run. If you have a lot of circles you probably want to look into spatial search algorithms.
Upvotes: 1