private static UIElement GetPolyLine(Point from, Point to, Brush stroke) { var line = new ArrowPolyline(); line.Stroke = stroke; line.StrokeThickness = 2.0; line.ArrowEnds = ArrowEnds.End; line.ArrowLength = 8; line.Points.Add(from); if (from.Y != to.Y) { line.Points.Add(new Point(from.X, to.Y)); } line.Points.Add(to); return(line); }
private void DrawLinks() { // remove all links drawnLinks.Clear(); for (int i = 0; i <= graphCanvas.Children.Count - 1; i++) { var child = graphCanvas.Children[i]; if (child is ArrowLineBase) { graphCanvas.Children.RemoveAt(i); i--; } } // draw links foreach (var node in drawnNodes.Keys) { Point startPosition = drawnNodes[node].Point; foreach (var link in node.Links) { if (drawnLinks.ContainsKey(link)) { continue; } if (link.IsLoop) { ArrowPolyline apoly = new ArrowPolyline() { Stroke = this.linkColor, StrokeThickness = 0.5, ArrowAngle = 25, ArrowLength = 6 }; apoly.ArrowEnds = graph.GraphType == GraphType.Undirected ? ArrowEnds.None : ArrowEnds.End; Point nodePosition = drawnNodes[link.Node1].Point; apoly.Points.Add(nodePosition); apoly.Points.Add(new Point(nodePosition.X, nodePosition.Y + nodeRadius * 2)); apoly.Points.Add(new Point(nodePosition.X + nodeRadius * 2, nodePosition.Y + nodeRadius * 2)); apoly.Points.Add(new Point(nodePosition.X + nodeRadius * 2, nodePosition.Y)); apoly.Points.Add(new Point(nodePosition.X + nodeRadius, nodePosition.Y)); graphCanvas.Children.Add(apoly); drawnLinks.Add(link, apoly); Label lbl = new Label() { Content = link.Weight.ToString(), Foreground = nodeNameColor, FontWeight = FontWeights.Bold }; Canvas.SetLeft(lbl, apoly.Points.Last().X + nodeRadius); Canvas.SetTop(lbl, apoly.Points.Last().Y + nodeRadius); Canvas.SetZIndex(lbl, 101); graphCanvas.Children.Add(lbl); } else { Point endPosition = drawnNodes[link.Node2].Point; if (graph.GraphType == GraphType.Undirected) { if (node == link.Node2) { endPosition = drawnNodes[link.Node1].Point; } } Petzold.Media2D.ArrowLine line = new Petzold.Media2D.ArrowLine() { Stroke = this.linkColor, StrokeThickness = 1, ArrowAngle = 25, ArrowLength = 6 }; line.ArrowEnds = graph.GraphType == GraphType.Undirected ? ArrowEnds.None : ArrowEnds.End; line.X1 = startPosition.X; line.Y1 = startPosition.Y; Point endPoint = new Point(); if (endPosition.X - startPosition.X == 0 || endPosition.Y - startPosition.Y == 0) { endPoint.X = endPosition.X; endPoint.Y = endPosition.Y; } else { double alpha = Math.Atan(Math.Abs((endPosition.Y - startPosition.Y) / (endPosition.X - startPosition.X))); double sinAlpha = Math.Abs(Math.Sin(alpha)); double cosAlpha = Math.Abs(Math.Cos(alpha)); if (endPosition.X > startPosition.X && endPosition.Y < startPosition.Y) //first quarter { endPoint.X = endPosition.X - ((double)nodeRadius) * cosAlpha; endPoint.Y = endPosition.Y + ((double)nodeRadius) * sinAlpha; } else if (endPosition.X > startPosition.X && endPosition.Y > startPosition.Y) //second quarter { endPoint.X = endPosition.X - ((double)nodeRadius) * cosAlpha; endPoint.Y = endPosition.Y - ((double)nodeRadius) * sinAlpha; } else if (endPosition.X < startPosition.X && endPosition.Y > startPosition.Y) //third quarter { endPoint.X = endPosition.X + ((double)nodeRadius) * cosAlpha; endPoint.Y = endPosition.Y - ((double)nodeRadius) * sinAlpha; } else if (endPosition.X < startPosition.X && endPosition.Y < startPosition.Y) //fourth quarter { endPoint.X = endPosition.X + ((double)nodeRadius) * cosAlpha; endPoint.Y = endPosition.Y + ((double)nodeRadius) * sinAlpha; } } line.X2 = endPoint.X; line.Y2 = endPoint.Y; graphCanvas.Children.Add(line); line.MouseDown += Line_MouseDown; line.Tag = link; drawnLinks.Add(link, line); Canvas.SetZIndex(line, 99); // add link weight to canvas var p = new Point((line.X1 + line.X2) / 2, (line.Y1 + line.Y2) / 2); Label lbl = new Label() { Content = link.Weight.ToString(), Foreground = nodeNameColor, FontWeight = FontWeights.Bold }; Canvas.SetLeft(lbl, p.X - nodeRadius); Canvas.SetTop(lbl, p.Y - nodeRadius); Canvas.SetZIndex(lbl, 101); graphCanvas.Children.Add(lbl); } } } }
/// <summary> /// The arrow demo is uses an adaption of Charles Petzold's WPF arrow class /// http://charlespetzold.com/blog/2007/04/191200.html to be used as custom MapShape /// </summary> /// <param name="layer"></param> public void AddArrows(ShapeLayer layer) { // ArrowLine with animated arrow properties. var arrowLine1 = new ArrowLine { Stroke = Brushes.Red, MapStrokeThickness = 30, ScaleFactor = .25, ArrowLength = 3, X1 = 8.100, Y1 = 49.400, X2 = 8.400, Y2 = 49.100 }; // the adaptive stroke thickness // the scale factor [0..1]. 0: Don't scale (thickness = pixels); 1: scale linear (thickness = mercator units) // the arrow length is relative to the arrow stroke thickness layer.Shapes.Add(arrowLine1); var doubleAnimation1 = new DoubleAnimation(10, 50, new Duration(new TimeSpan(0, 0, 5))) { AutoReverse = true, RepeatBehavior = RepeatBehavior.Forever }; arrowLine1.BeginAnimation(ArrowLineBase.ArrowAngleProperty, doubleAnimation1); var doubleAnimation2 = new DoubleAnimation(1, 20, new Duration(new TimeSpan(0, 0, 5))) { AutoReverse = true, RepeatBehavior = RepeatBehavior.Forever }; arrowLine1.BeginAnimation(ArrowLineBase.ArrowLengthProperty, doubleAnimation2); // ArrowLine with animated point properties. var arrowLine2 = new ArrowLine { ArrowEnds = ArrowEnds.Both, Stroke = Brushes.Blue, MapStrokeThickness = 30, ScaleFactor = .25 }; arrowLine1.ArrowLength = 3; arrowLine2.X1 = 8.100; arrowLine2.Y1 = 49.100; arrowLine2.X2 = 8.200; arrowLine2.Y2 = 49.400; layer.Shapes.Add(arrowLine2); AnimationTimeline doubleAnimation3 = new DoubleAnimation(8.100, 8.400, new Duration(new TimeSpan(0, 0, 5))); doubleAnimation3.AutoReverse = true; doubleAnimation3.RepeatBehavior = RepeatBehavior.Forever; arrowLine2.BeginAnimation(ArrowLine.X1Property, doubleAnimation3); AnimationTimeline doubleAnimation4 = new DoubleAnimation(49.400, 49.100, new Duration(new TimeSpan(0, 0, 5))); doubleAnimation4.AutoReverse = true; doubleAnimation4.RepeatBehavior = RepeatBehavior.Forever; arrowLine2.BeginAnimation(ArrowLine.Y2Property, doubleAnimation4); // ArrowPolyline rotated. var arrowPolyline = new ArrowPolyline { ArrowEnds = ArrowEnds.Both, Stroke = Brushes.Green, MapStrokeThickness = 30, ScaleFactor = .25 }; arrowLine1.ArrowLength = 3; arrowPolyline.Points.Add(new Point(8.25, 49.25)); arrowPolyline.Points.Add(new Point(8.125, 49.25)); arrowPolyline.Points.Add(new Point(8.125, 49.125)); arrowPolyline.Points.Add(new Point(8.25, 49.125)); layer.Shapes.Add(arrowPolyline); // the rotation center of the canvas needs to be calculated for a rotate transform // only works after the shape has been added to the canvas. var rotateCenter = arrowPolyline.GeoTransform(new Point(8, 49)); var rotateTransform = new RotateTransform(0, rotateCenter.X, rotateCenter.Y); arrowPolyline.RenderTransform = rotateTransform; AnimationTimeline animaDouble5 = new DoubleAnimation(0, 360, new Duration(new TimeSpan(0, 0, 10))); animaDouble5.RepeatBehavior = RepeatBehavior.Forever; rotateTransform.BeginAnimation(RotateTransform.AngleProperty, animaDouble5); }