I have 2 (VisualBasic.PowerPacks)LineShapes on my form:
alt text http://lh4.ggpht.com/_1TPOP7DzY1E/S2cIJan7eHI/AAAAAAAADAw/qwA0jFHEbBM/s800/intersection.png
When I click on one of them, a specific context menu appears. The lines can be moved by the user. A context Menu is associated with a line. However, if the user clicks in the intersection point(if exists) I need to display an other menu, that will select one of intersection lines to perform an action.
Now, I wonder how to detect that 2 (or more) lines are intersected in 开发者_运维问答the click point, because an other context-menu should appear in this case.
What I tried to do:
private void shapeContainer1_MouseDown(object sender, MouseEventArgs e)
{
// right click only
if (e.Button == MouseButtons.Right)
{
LineShape target =
(shapeContainer1.GetChildAtPoint(e.Location) as LineShape);
if (target != null)
{
Console.WriteLine(new Point(target.X1, target.Y1));
}
}
}
I suppose I have only LineShapes in the container. This told, the ShapeContainer will not raise a MouseDown event if any LineShape will be under the mouse.
But this code gives me only the mostTop line, but I want a list of others too.
In your coordinate network, you have two lines with y1 = ax + c1
and y2 = bx + c2
. Find the intersection point where x1=x2
and y1=y2
y = ax + c1, y = bx + c2
ax + c1 = bx + c2
x = (c2 - c1)/(a - b)
Then check that the intersection point is not beyond the line borders and calculate proximity +- pixel or two.
You'll need to just compute the intersection of two line segments. This is fairly simple.
A full, working algorithm is described here. It works off line segments defined by two points, so should be easy to adapt to your situation.
serhio, thats simple Maths...
Work out the intersection points of your lines (probably do this when they are added and store result), then see if the mouse is close enough to warrent displaying the context menu so you don't need pixel perfect clicking.
Apart from the line intersection algorithm (as shown by several people on this page), you need to decouple the context menu from the lines. In pseudo code you'll need something like:
onLine1Click:
if intersection then handle intersection
else handle line1 click
onLine2Click:
if intersection then handle intersection
else handle line2 click
This handling can be showing the context menu. I believe this if/then/else is required to resolve your remaining issue.
/// obtains a list of shapes from a click point
private List<LineShape> GetLinesFromAPoint(Point p)
{
List<LineShape> result = new List<LineShape>();
Point pt = shapeContainer1.PointToScreen(p);
foreach (Shape item in shapeContainer1.Shapes)
{
LineShape line = (item as LineShape);
if (line != null && line.HitTest(pt.X, pt.Y))
{
result.Add(line);
}
}
return result;
}
private void shapeContainer1_MouseDown(object sender, MouseEventArgs e)
{
// right click only
if (e.Button == MouseButtons.Right)
{
List<LineShape> shapesList = GetLinesFromAPoint(e.Location);
Console.WriteLine(DateTime.Now);
Console.WriteLine("At this point {0} there are {1} lines.",
e.Location, shapesList.Count);
}
}
精彩评论