protected void IterateOne() { //create the forces (zero forces) var forces = new Dictionary <TVertex, VectorStd>(); #region Repulsive forces var force = new VectorStd(0, 0); foreach (TVertex v in VisitedGraph.Vertices) { force.X = 0; force.Y = 0; SKPoint posV = VertexPositions[v]; foreach (TVertex u in VisitedGraph.Vertices) { //doesn't repulse itself if (u.Equals(v)) { continue; } //calculating repulsive force VectorStd delta = VectorStd.DifferenceVector(posV, VertexPositions[u]); float length = (float)Math.Max(delta.Length, double.Epsilon); delta = delta / length * Parameters.ConstantOfRepulsion / length; force += delta; } forces[v] = force; } #endregion #region Attractive forces foreach (TEdge e in VisitedGraph.Edges) { TVertex source = e.Source; TVertex target = e.Target; //vonzóerõ számítása a két pont közt VectorStd delta = VectorStd.DifferenceVector(VertexPositions[source], VertexPositions[target]); float length = (float)Math.Max(delta.Length, double.Epsilon); delta = delta / length * ((float)Math.Pow(length, 2)) / Parameters.ConstantOfAttraction; forces[source] -= delta; forces[target] += delta; } #endregion #region Limit displacement foreach (TVertex v in VisitedGraph.Vertices) { SKPoint pos = VertexPositions[v]; //erõ limitálása a temperature-el VectorStd delta = forces[v]; float length = (float)Math.Max(delta.Length, double.Epsilon); delta = delta / length * (float)Math.Min(delta.Length, _temperature); //erõhatás a pontra pos += delta; //falon ne menjünk ki pos.X = (float)Math.Min(_maxWidth, Math.Max(0, pos.X)); pos.Y = (float)Math.Min(_maxHeight, Math.Max(0, pos.Y)); VertexPositions[v] = pos; } #endregion }
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); } } }
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; } } }
protected void CopyPositionsSilent(bool shouldTranslate) { //calculate the topLeft position var translation = new VectorStd(float.PositiveInfinity, float.PositiveInfinity); if (shouldTranslate) { foreach (var v in _graph.Vertices) { if (double.IsNaN(v.RealPosition.X) || double.IsNaN(v.RealPosition.Y)) { continue; } translation.X = Math.Min(v.RealPosition.X, translation.X); translation.Y = Math.Min(v.RealPosition.Y, translation.Y); } translation *= -1; translation.X += Parameters.VerticalGap / 2; translation.Y += Parameters.HorizontalGap / 2; //translate with the topLeft position foreach (var v in _graph.Vertices) { v.RealPosition += translation; } } else { translation = new VectorStd(0, 0); } //copy the positions of the vertices VertexPositions.Clear(); foreach (var v in _graph.Vertices) { if (v.IsDummyVertex) { continue; } SKPoint pos = v.RealPosition; if (!shouldTranslate) { pos.X += v.Size.Width * 0.5f + translation.X; pos.Y += v.Size.Height * 0.5f + translation.Y; } VertexPositions[v.Original] = pos; } //copy the edge routes EdgeRoutes.Clear(); foreach (var e in _graph.HiddenEdges) { if (!e.IsLongEdge) { continue; } EdgeRoutes[e.Original] = e.IsReverted ? e.DummyVertices.Reverse().Select(dv => dv.RealPosition).ToArray() : e.DummyVertices.Select(dv => dv.RealPosition).ToArray(); } }