예제 #1
0
        private (SKPoint edgeSource, SKPoint edgeTarget) AddEdgePath(List <SKPoint> edgePath, Kaemika.Edge <Vertex> edge)
        {
            SKPoint source     = layoutInfo.vertexPositions[edge.Source];
            SKPoint target     = layoutInfo.vertexPositions[edge.Target];
            SKSize  sourceSize = layoutInfo.vertexSizes[edge.Source];
            SKSize  targetSize = layoutInfo.vertexSizes[edge.Target];

            if (layoutInfo.edgeRoutes == null)
            {
                layoutInfo.edgeRoutes = new Dictionary <Kaemika.Edge <Vertex>, SKPoint[]>();
            }
            SKPoint[] route = (layoutInfo.edgeRoutes.ContainsKey(edge)) ? layoutInfo.edgeRoutes[edge] : new SKPoint[] { };

            SKPoint initialTarget = (route.Length == 0) ? target : route[0];
            SKPoint firstSource   = PointOnRectangle(source, initialTarget, sourceSize.Width / 2, sourceSize.Height / 2);

            edgePath.Add(firstSource);
            SKPoint lastSource = firstSource;

            foreach (var nextTarget in route)
            {
                edgePath.Add(nextTarget);
                lastSource = nextTarget;
            }
            SKPoint lastTarget  = PointOnRectangle(target, lastSource, targetSize.Width / 2, targetSize.Height / 2);
            SKPoint firstTarget = (route.Length == 0) ? lastTarget : initialTarget;

            if (!(edge.Target is Vertex_Routing))
            {
                edgePath.Add(lastTarget);
            }
            return(firstSource, firstTarget);
        }
예제 #2
0
        private void DrawSplineEdge(SKCanvas canvas, Kaemika.Edge <Vertex> edge, float nodeHeight, float textSize, SKColor color, Swipe swipe)
        {
            if (edge.Source is Vertex_Routing)
            {
                return;                                // this edge it will be drawn as part of another edge
            }
            List <SKPoint> edgePath = new List <SKPoint>();

            Kaemika.Edge <Vertex> routedEdge = edge;
            (SKPoint firstSource, SKPoint firstTarget) = AddEdgePath(edgePath, routedEdge);
            while (routedEdge.Target is Vertex_Routing)
            {
                routedEdge = (routedEdge.Target as Vertex_Routing).toEdge;
                AddEdgePath(edgePath, routedEdge);
            }
            edgePath.Insert(0, edgePath[0]); // duplicate first point for spline
            SKPoint ultimate    = edgePath[edgePath.Count - 1];
            SKPoint penultimate = edgePath[edgePath.Count - 2];

            edgePath.Insert(edgePath.Count, ultimate); // duplicate last point for spline
            List <SKPoint> controlPoints = ControlPoints(edgePath);
            SKPath         path          = AddBeziers(new SKPath(), controlPoints.ToArray(), swipe);

            using (var paint = new SKPaint()) {
                paint.TextSize = 10.0f; paint.IsAntialias = true; paint.Color = color; paint.IsStroke = true;
                canvas.DrawPath(path, paint);

                SKPoint arrowHeadBase = ultimate;
                if (routedEdge.Directed != Directed.No)   // draw arrowhead on last routedEdge segment, update arrowHeadBase
                {
                    VectorStd lineVector = VectorStd.DifferenceVector(ultimate, penultimate);
                    float     lineLength = lineVector.Length;
                    // calculate point at base of arrowhead
                    float     arrowWidth         = nodeHeight / 6;
                    float     tPointOnLine       = (float)(arrowWidth / (2 * (Math.Tan(120) / 2) * lineLength));
                    VectorStd arrowReverseVector = -tPointOnLine * lineVector;
                    arrowHeadBase = ultimate + arrowReverseVector;
                    SKPoint   arrowHeadMid = ultimate + (0.5F * arrowReverseVector);
                    VectorStd normalVector = new VectorStd(-lineVector.Y, lineVector.X);
                    float     tNormal      = arrowWidth / (2 * lineLength);
                    SKPoint   leftPoint    = arrowHeadBase + tNormal * normalVector;
                    SKPoint   rightPoint   = arrowHeadBase + -tNormal * normalVector;
                    if (routedEdge.Directed == Directed.Solid)
                    {
                        var arrowPath = new SKPath(); paint.IsStroke = false;
                        arrowPath.MoveTo(swipe % leftPoint); arrowPath.LineTo(swipe % ultimate);
                        arrowPath.LineTo(swipe % rightPoint); arrowPath.Close();
                        canvas.DrawPath(arrowPath, paint);
                    }
                    if (routedEdge.Directed == Directed.Pointy)
                    {
                        var arrowPath = new SKPath(); paint.IsStroke = true;
                        arrowPath.MoveTo(swipe % leftPoint); arrowPath.LineTo(swipe % ultimate);
                        arrowPath.LineTo(swipe % rightPoint);
                        canvas.DrawPath(arrowPath, paint);
                    }
                    if (routedEdge.Directed == Directed.Ball)
                    {
                        var arrowPath = new SKPath(); paint.IsStroke = false;
                        canvas.DrawCircle(swipe % arrowHeadMid, swipe % (arrowReverseVector.Length / 2), paint);
                    }
                }
                // if (routedEdge.Directed == Directed.Solid) { paint.IsStroke = false; canvas.DrawCircle(path.LastPoint, 20, paint); }
                // if (routedEdge.Directed == Directed.Pointy) { paint.IsStroke = true; canvas.DrawCircle(path.LastPoint, 20, paint); }

                if (edge.Label != null)   // draw label on first routedEdge segment
                {
                    var saveTextSize = paint.TextSize;
                    paint.TextSize = swipe % textSize / 3;
                    SKPoint labelTarget = (firstTarget == ultimate) ? arrowHeadBase : firstTarget;
                    GraphLayout.CanvasDrawTextCentered(canvas, edge.Label, swipe % new SKPoint((firstSource.X + labelTarget.X) / 2, (firstSource.Y + labelTarget.Y) / 2), paint, true);
                    paint.TextSize = saveTextSize;
                }
            }
        }
예제 #3
0
        private void DrawEdge(SKCanvas canvas, Kaemika.Edge <Vertex> edge, float nodeHeight, float textSize, SKColor color, Swipe swipe)
        {
            bool spline = false; bool arc = false;

            using (var paint = new SKPaint()) {
                paint.TextSize = 10.0f; paint.IsAntialias = true; paint.Color = color;

                SKPoint source     = layoutInfo.vertexPositions[edge.Source];
                SKPoint target     = layoutInfo.vertexPositions[edge.Target];
                SKSize  sourceSize = layoutInfo.vertexSizes[edge.Source];
                SKSize  targetSize = layoutInfo.vertexSizes[edge.Target];

                if (layoutInfo.edgeRoutes == null)
                {
                    layoutInfo.edgeRoutes = new Dictionary <Kaemika.Edge <Vertex>, SKPoint[]>();
                }
                SKPoint[] route = (layoutInfo.edgeRoutes.ContainsKey(edge)) ? layoutInfo.edgeRoutes[edge] : new SKPoint[] { };

                var     routePath     = new SKPath(); paint.IsStroke = true;
                SKPoint initialTarget = (route.Length == 0) ? target : route[0];
                SKPoint firstSource   = PointOnRectangle(source, initialTarget, sourceSize.Width / 2, sourceSize.Height / 2);
                routePath.MoveTo(swipe % firstSource);
                SKPoint lastSource = firstSource;
                foreach (var nextTarget in route)
                {
                    if (spline)
                    {
                        (SKPoint control, SKPoint nextControl) = SplineControls(lastSource, nextTarget, new SKSize(textSize, textSize));
                        routePath.CubicTo(swipe % control, swipe % nextControl, swipe % nextTarget);
                    }
                    else
                    {
                        routePath.LineTo(swipe % nextTarget);
                    }
                    lastSource = nextTarget;
                }
                SKPoint lastTarget  = PointOnRectangle(target, lastSource, targetSize.Width / 2, targetSize.Height / 2);
                SKPoint firstTarget = (route.Length == 0) ? lastTarget : initialTarget;
                if (spline)
                {
                    (SKPoint control, SKPoint nextControl) = SplineControls(lastSource, lastTarget, new SKSize(textSize, textSize));
                    routePath.CubicTo(swipe % control, swipe % nextControl, swipe % lastTarget);
                }
                else if (arc && route.Length == 0)
                {
                    routePath.ArcTo(swipe % lastSource, swipe % lastTarget, swipe % textSize);                                // see Postscript arct
                }
                else
                {
                    routePath.LineTo(swipe % lastTarget);
                }
                canvas.DrawPath(routePath, paint);

                SKPoint arrowHeadBase = lastTarget;

                //SKPoint nextSource = source;
                //foreach (var nextTarget in route) {
                //    if (nextSource == source) nextSource = PointOnRectangle(source, nextTarget, sourceSize.Width / 2, sourceSize.Height / 2);
                //    canvas.DrawLine(swipe % nextSource, swipe % nextTarget, paint);
                //    nextSource = nextTarget;
                //}
                //SKPoint lastSource = (nextSource != source) ? nextSource : PointOnRectangle(source, target, sourceSize.Width / 2, sourceSize.Height / 2);
                //SKPoint lastTarget = PointOnRectangle(target, lastSource, targetSize.Width / 2, targetSize.Height / 2);
                //canvas.DrawLine(swipe % lastSource, swipe % lastTarget, paint);

                //SKPoint pointOnLine = lastTarget;

                if (edge.Directed != Directed.No)   // draw arrowhead, update arrowHeadBase
                {
                    VectorStd lineVector = VectorStd.DifferenceVector(lastTarget, lastSource);
                    float     lineLength = lineVector.Length;
                    // calculate point at base of arrowhead
                    float arrowWidth   = nodeHeight / 6;
                    float tPointOnLine = (float)(arrowWidth / (2 * (Math.Tan(120) / 2) * lineLength));
                    arrowHeadBase = lastTarget + (-tPointOnLine * lineVector);
                    VectorStd normalVector = new VectorStd(-lineVector.Y, lineVector.X);
                    float     tNormal      = arrowWidth / (2 * lineLength);
                    SKPoint   leftPoint    = arrowHeadBase + tNormal * normalVector;
                    SKPoint   rightPoint   = arrowHeadBase + -tNormal * normalVector;
                    if (edge.Directed == Directed.Solid)
                    {
                        var arrowPath = new SKPath(); paint.IsStroke = false;
                        arrowPath.MoveTo(swipe % leftPoint); arrowPath.LineTo(swipe % lastTarget);
                        arrowPath.LineTo(swipe % rightPoint); arrowPath.Close();
                        canvas.DrawPath(arrowPath, paint);
                    }
                    if (edge.Directed == Directed.Pointy)
                    {
                        var arrowPath = new SKPath(); paint.IsStroke = true;
                        arrowPath.MoveTo(swipe % leftPoint); arrowPath.LineTo(swipe % lastTarget);
                        arrowPath.LineTo(swipe % rightPoint);
                        canvas.DrawPath(arrowPath, paint);
                    }
                }

                if (edge.Label != null)   // draw label
                {
                    var saveTextSize = paint.TextSize;
                    paint.TextSize = swipe % textSize / 3;
                    SKPoint labelTarget = (route.Length == 0) ? arrowHeadBase : firstTarget;
                    GraphLayout.CanvasDrawTextCentered(canvas, edge.Label, swipe % new SKPoint((firstSource.X + labelTarget.X) / 2, (firstSource.Y + labelTarget.Y) / 2), paint, true);
                    paint.TextSize = saveTextSize;
                    //var path = new SKPath(); paint.IsStroke = false;
                    //path.MoveTo(swipe % firstSource);
                    //path.LineTo(swipe % ((route.Length == 0) ? arrowHeadBase : firstTarget));
                    //path.Close(); // so the text wraps back around the closed single-line path
                    //paint.TextSize = swipe % textSize / 3;
                    //canvas.DrawTextOnPath(edge.Label, path, new SKPoint(paint.TextSize/2, -paint.TextSize/2), paint);
                }
            }
        }