/// <summary> /// Determines if the given Point is near any of the lines in /// Lines.LinesList. Sets HitLine to the first found or null if /// none found. /// </summary> /// <param name="point">The input point in PictureBox coordinates.</param> /// <returns>If found.</returns> public bool hitTestLine(Point point) { if (ActiveMode != Mode.EDIT) { return(false); } Point imgPoint = imagePoint(point); bool res; HitLine = null; HitPoint = null; Debug.WriteLine("hitTestLine: ActiveMode=" + ActiveMode + " ZoomFactor=" + ZoomFactor + NL + " point=" + point + " imgPoint=" + imgPoint + NL + " LINE_WIDTH=" + LINE_WIDTH + " HIT_TOLERANCE=" + HIT_TOLERANCE); foreach (Line line in Lines.LinesList) { // First check the points // (Tolerance does not extend past the ends as it does transverse.) Region region; foreach (Point point1 in line.Points) { region = new Region(centeredSquare(point1, HIT_TOLERANCE)); res = region.IsVisible(imgPoint); if (res) { HitPoint = new HitPoint(line, line.Points.IndexOf(point1)); HitLine = line; return(true); } } // Then check the lines. using (var path = new GraphicsPath()) using (var pen = new Pen(Color.Black, HIT_TOLERANCE)) { for (int i = 1; i < line.NPoints; i++) { path.AddLine(line.Points[i - 1], line.Points[i]); } res = path.IsOutlineVisible(imgPoint, pen); if (res) { HitLine = line; return(true); } } } return(false); }
/// <summary> /// Adds a point to the HitLine after the point corresponding to the /// given Point and located between it and the next point at a distance /// depending on the ratio of the distances between those points and /// the diven point. If there is only one point in the line nothing will be done. /// </summary> /// <param name="point"></param> public void addPoint(Point point) { if (HitLine == null) { return; } Point imgPoint = imagePoint(point); List <Point> points = HitLine.Points; int count = points.Count; // Be sure there is more than one point if (count <= 1) { return; } Point lineStart = INVALID_POINT; bool res; // First check the points // (Tolerance does not extend past the ends as it does transverse.) Region region; foreach (Point point1 in points) { region = new Region(centeredSquare(point1, HIT_TOLERANCE)); res = region.IsVisible(imgPoint); if (res) { lineStart = point1; break; } } // Then check the lines. if (lineStart == INVALID_POINT) { for (int i = 1; i < HitLine.NPoints; i++) { using (var path = new GraphicsPath()) using (var pen = new Pen(Color.Black, HIT_TOLERANCE)) { path.AddLine(points[i - 1], points[i]); res = path.IsOutlineVisible(imgPoint, pen); if (res) { lineStart = HitLine.Points[i - 1]; break; } } } } if (lineStart == INVALID_POINT) { return; } int indexStart = points.IndexOf(lineStart); if (indexStart == count - 1) { indexStart--; } if (points.IndexOf(lineStart) == count - 1) { lineStart = points[count - 2]; } Point lineEnd = points[indexStart + 1]; double distance12 = lineLength(lineStart, lineEnd); double distance01 = lineLength(lineStart, imgPoint); double distance02 = lineLength(imgPoint, lineEnd); double ratio; if (distance01 == 0 && distance02 == 0) { ratio = 0; } else { ratio = distance01 / (distance01 + distance02); } int x2 = (int)Math.Round(lineStart.X + ratio * (lineEnd.X - lineStart.X)); int y2 = (int)Math.Round(lineStart.Y + ratio * (lineEnd.Y - lineStart.Y)); Point newPoint = new Point(x2, y2); int newIndex = indexStart + 1; points.Insert(indexStart + 1, newPoint); HitPoint = new HitPoint(HitLine, newIndex); }