This is a migrated thread and some comments may be shown as answers.

How do i know connection contains point?

2 Answers 66 Views
Diagram
This is a migrated thread and some comments may be shown as answers.
seokhyun
Top achievements
Rank 1
Veteran
seokhyun asked on 20 Feb 2020, 07:02 AM
Hello,



I'm sorry to leave so many questions.

Here's the question.

I'd like to find out if the point above the diagram is within the connection.

Other DiagramItems, such as Shape, could calculate to Shape.Bounds.Contains(point).

However, the connection is a line, so if you calculate it as Bounds, there is a problem that i can't measure properly.

I want to get a bool value for the point above the connection or, if possible, within an interval between 1 and 5 around the connection line.

Connection.Geometry has a different position value and connection.Geometry doesn't have been activated by fillcontains or stalkcontains.

2 Answers, 1 is accepted

Sort by
0
Petar Mladenov
Telerik team
answered on 24 Feb 2020, 04:05 PM

Hi seokhyun,

What you describe is very similar to our connection hit testing internal logic which we perform when clicking with mouse. 

I will post some code and I hope you will get the idea of the hit testing logic.

Telerik.Windows.Diagrams.Core.HitTestService:

        /// <summary>
        /// Gets the items near point.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <param name="delta">The delta.</param>
        /// <returns></returns>
        public IEnumerable<IDiagramItem> GetItemsNearPoint(Point point, double delta)
        {
            var foundItems = new List<IDiagramItem>();

            foundItems.AddRange(this.GetShapesNearPoint(point, delta));
            var deltaOffset = delta / 2d;
            foundItems.AddRange(this.GetConnectionsUnderRect(new Rect(new Point(point.X - deltaOffset, point.Y - deltaOffset), new Point(point.X + deltaOffset, point.Y + deltaOffset))));

            return foundItems;
        }

  /// <summary>
        /// Gets the connections intersecting the specific rectangle.
        /// </summary>
        /// <param name="rect"></param>
        /// <returns></returns>
        public IEnumerable<IConnection> GetConnectionsUnderRect(Rect rect)
        {
            var foundConnections = new List<IConnection>();

            foreach (var connection in this.Graph.Connections.Where(connection => connection.Visibility == Visibility.Visible && connection.IsEnabled))
            {
                if (rect.Contains(connection.Bounds))
                {
                    // whatever the type, if it's contained in the given rectangle it's selected
                    foundConnections.Add(connection);
                    continue;
                }

                switch (connection.ConnectionType)
                {
                    case ConnectionType.Spline:
                        {
                            var geometry = connection.Geometry as PathGeometry;
                            if (!geometry.Figures.Any()) return foundConnections;

                            // here is the fact that the possibly the first two figures are caps, the line itself sits in the last figure
                            var lines = geometry.Figures[geometry.Figures.Count - 1].Segments.OfType<PolyLineSegment>();
                            var polyLineSegments = lines as PolyLineSegment[] ?? lines.ToArray();
                            var points = polyLineSegments.Any() ? polyLineSegments.First().Points : new PointCollection { connection.EndPoint };
                            var clone = points.Clone().ToList();
                            clone.Insert(0, geometry.Figures[0].StartPoint);
                            var newRect = new Rect(rect.X - connection.Position.X, rect.Y - connection.Position.Y, rect.Width, rect.Height);
                            if (newRect.IntersectsLine(clone)) foundConnections.Add(connection);
                        }
                        break;
                    case ConnectionType.Polyline:
                        {
                            var points = new List<Point>(connection.ConnectionPoints);
                            points.Insert(0, connection.StartPoint);
                            points.Add(connection.EndPoint);
                            if (rect.Contains(connection.Bounds) || rect.IntersectsLine(points)) foundConnections.Add(connection);
                        }
                        break;
                    case ConnectionType.Bezier:
                        {
                            if (connection.ConnectionPoints.Count == 0)
                            {
                                // This ensures the connection points are not empty.
                                connection.Update();
                            }
                            var bezierPoints = new[] { connection.StartPoint, Utils.Lerp(connection.StartPoint, connection.ConnectionPoints[0], connection.BezierTension), Utils.Lerp(connection.EndPoint, connection.ConnectionPoints[1], connection.BezierTension), connection.EndPoint };
                            var approximatedBezierPoints = Utils.ApproximateBezierCurve(bezierPoints, 30);
                            if (rect.IntersectsLine(approximatedBezierPoints.ToList())) foundConnections.Add(connection);
                        }
                        break;
                }
            }

            return foundConnections;
        }

The delta parameter is usually DiagramContants.SelectionHitTestRadius (10 by default). Most of the code uses either public extension methods or properties in the static Telerik.Windows.Diagrams.Core.Utils class which is very helpful regarding mathematics , geometry calculations etc.

Regards,
Petar Mladenov
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
seokhyun
Top achievements
Rank 1
Veteran
answered on 26 Feb 2020, 12:07 AM

Thank you for your help.

It's working. 

Tags
Diagram
Asked by
seokhyun
Top achievements
Rank 1
Veteran
Answers by
Petar Mladenov
Telerik team
seokhyun
Top achievements
Rank 1
Veteran
Share this question
or