Exemplo n.º 1
0
        /// <summary>
        /// Returns a collection of all the line segments (within certain % range) to all the nodes the current node links to
        /// </summary>
        /// <param name="skipPercent">The skip percentage, all segments before the given % will be ignored</param>
        /// <param name="takePercent">The amount of segments to take</param>
        /// <returns></returns>
        internal protected virtual IEnumerable <KeyValuePair <Point, Point> > GetLineSegmentsOfLinks(float skipPercent, float takePercent)
        {
            Rectangle area = Area;

            List <KeyValuePair <Point, Point> > segments = new List <KeyValuePair <Point, Point> >();

            var nodes = GetLinkedNodes().ToArray();
            int index = 0;

            foreach (var subn in nodes)
            {
                if (subn != null)
                {
                    // get the start & end positions of the line segment
                    Point source;
                    Point dest;
                    GetSourceAndDestPointsForLink(area, nodes.Length, index, subn, out source, out dest);
                    PointF[] points = GetPointsForLink(subn, source, dest);

                    var segmentsOfLink = new List <KeyValuePair <Point, Point> >();

                    // generate line segments based on the line type
                    if (parent.LineType == LineTypeEnum.Bezier)
                    {
                        LinkManager.DoBezier(points, 100, (p, p2) =>
                        {
                            segmentsOfLink.Add(new KeyValuePair <Point, Point>(new Point((int)p.X, (int)p.Y), new Point((int)p2.X, (int)p2.Y)));
                        });
                    }
                    else if (parent.LineType == LineTypeEnum.FourWay)
                    {
                        LinkManager.Do4WayLines(points, (p, p2) =>
                        {
                            segmentsOfLink.Add(new KeyValuePair <Point, Point>(new Point((int)p.X, (int)p.Y), new Point((int)p2.X, (int)p2.Y)));
                        });
                    }
                    else if (parent.LineType == LineTypeEnum.Straight)
                    {
                        LinkManager.DoStraight(points, (p, p2) =>
                        {
                            segmentsOfLink.Add(new KeyValuePair <Point, Point>(new Point((int)p.X, (int)p.Y), new Point((int)p2.X, (int)p2.Y)));
                        });
                    }
                    // add the segments to the collection
                    segments.AddRange(segmentsOfLink.Skip((int)(skipPercent * segmentsOfLink.Count)).Take((int)(takePercent * segmentsOfLink.Count)));
                }
                index++;
            }

            return(segments);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Draw the link with the bezier algorithm to get the line segments
        /// </summary>
        /// <param name="g">The graphics object</param>
        /// <param name="viewportRect">The viewport bounds</param>
        /// <param name="color">The color of the line segements</param>
        /// <param name="points">The points to do bezier with</param>
        private void DrawBezier(Graphics g, Rectangle viewportRect, Color color, params PointF[] points)
        {
            LinkManager.DoBezier(points, 100, (pt1, pt2, progress) =>
            {
                Pen p = new Pen(Color.FromArgb(255, color), 1f);
                if (progress == 1)
                {
                    // at the end, draw an arrow
                    p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
                }

                // if the line falls inside the viewport, draw it
                if (viewportRect.IntersectsWithLine(pt1.X, pt1.Y, pt2.X, pt2.Y))
                {
                    g.DrawLine(p, pt1, pt2);
                }

                p.Dispose();
            });
        }
Exemplo n.º 3
0
        /// <summary>
        /// Tries to get a link at the given x,y coordinates
        /// </summary>
        /// <param name="x">The x coordinate</param>
        /// <param name="y">The y coordinate</param>
        /// <param name="l">The link if there is one at the given coordinates</param>
        /// <returns>True if a link is found</returns>
        internal bool TryGetLink(int x, int y, out Link l)
        {
            Rectangle area       = Area;
            Point     clickPoint = new Point(x, y);

            var nodes = GetLinkedNodes().ToArray();
            int index = 0;

            Link link      = default(Link);
            bool foundLink = false;

            // check all links to child nodes
            foreach (var subn in nodes)
            {
                if (subn != null)
                {
                    // get the source & dest point
                    Point source;
                    Point dest;
                    GetSourceAndDestPointsForLink(area, nodes.Length, index, subn, out source, out dest);

                    // get all the control points
                    PointF[] points = GetPointsForLink(subn, source, dest);

                    // define the line segment action
                    Action <PointF, PointF> lineSegmentAction = (p, p2) =>
                    {
                        // check if the distance between the line segment and the point clicked is smaller than 3
                        float distToLine = (float)GetPointToLineDistance(p, p2, clickPoint);
                        if (distToLine < 3)
                        {
                            // determine if the closest point to the line segment actually falls inside the segment
                            float normalLength = (float)Math.Sqrt((p2.X - p.X) * (p2.X - p.X) + (p2.Y - p.Y) * (p2.Y - p.Y));
                            float u            = (clickPoint.X - p.X) * (p2.X - p.X) + (clickPoint.Y - p.Y) * (p2.Y - p.Y);
                            u /= normalLength;

                            //PointF lineVector = new PointF((p2.X - p.X) / normalLength, (p2.Y - p.Y) / normalLength);
                            if (u > 0 && u < normalLength)
                            {
                                // link found
                                link      = new Link(this, subn, index);
                                foundLink = true;
                            }
                        }
                    };

                    // do the appropriate algorithm
                    if (parent.LineType == LineTypeEnum.Bezier)
                    {
                        LinkManager.DoBezier(points, 100, lineSegmentAction);
                    }
                    else if (parent.LineType == LineTypeEnum.FourWay)
                    {
                        LinkManager.Do4WayLines(points, lineSegmentAction);
                    }
                    else if (parent.LineType == LineTypeEnum.Straight)
                    {
                        LinkManager.DoStraight(points, lineSegmentAction);
                    }
                }
                index++;
            }

            l = link;
            return(foundLink);
        }