tags:

views:

26

answers:

4

I have a Path and when user click on a segment I have to split it into two segments.

I have the point where user click but I can't find a method to get the LineSegment that contains that point.

I don't have to find the Path element... but the LineSegment of a collection of Segment that create the PathGeometry of the Path clicked.

How can i do?

A: 

But you have Point property, so basically you've got a Collecion of n+1 Points. Line between points is a simple linien equation. You have to check if your mouse's point solve this equation (interates through the collection for all lines).

The equation: 0 = Ax + By + C or simply y = ax + b

There are many ways to get the parameters of it.

lukas
A: 

From geometry we know, that (y1 - y2) * x + (x2 - x1) * y + (x1*y2 - x2*y1) = 0, where x1, y1 is the firs point of your line segment and x2, y2 is the second one. This is the formula of the line. To determine, if a given point P(X, Y) belongs to the line, you have to substitute it's coordinates to your line formula's left side and the result on the right side should be 0, or 0 +- \epsilon.

But you have not a line, you have it's segment, so you will have to add more checks, for instance, Px should not be less than x1, and no more than x2, etc.

Shaman
A: 

To expand on what Shaman & lukas have said - what you really want to do is find the line segment that is nearest to to click point (As the user could not be expected to click exactly on the line)

To do this,go through each of the line segments and apply the `(y1 - y2) * x + (x2 - x1) * y + (x1*y2 - x2*y1)' formula to it and remove the sign of the answer - the line segmet that produces the smallest result is the one that is nearest to the click point.

If you have a lot of segments in your path, this might take a long time to execute, so there are probably some optimisations to be done - but that, as they say, is a whole new story.

belugabob
+1  A: 

I have some code that does this. Each of my points are stored in a Points collection rather than being stored as LineSegments, but it should work for you I think. The thickness parameter is the thickness of the line.

    public int HitTestSegments(Point point, double thickness)
    {
        for (int i = 0; i < Points.Count; ++i)
        {
            Point p0 = Points[i];
            Point p1 = (i + 1 < Points.Count) ? Points[i + 1] : Points[0];
            Vector v = p1 - p0;
            Vector w = point - p0;
            double c1 = w * v;
            double c2 = v * v;
            double b = c1 / c2;
            Point pb = p0 + b * v;
            double distance = (point - pb).Length;

            if (distance < thickness)
            {
                return i;
            }
        }

        return -1;
    }

I hacked this together from various samples on the internet, and my maths isn't amazing. It may not be the best code - if not, please suggest improvements.

Groky