private List <Point2D> RouteSpline(List <Point2D> anchorPoints) { var result = new List <Point2D>(); if (anchorPoints.Count == 0) { return(new List <Point2D>()); } Point2D point1 = anchorPoints[0]; result.Add(point1); for (int i = 2; i < anchorPoints.Count; i++) { var point2 = anchorPoints[i - 1]; var point3 = anchorPoints[i]; var anchor1 = GeomUtils.Interpolate(point1, point2, 1 - tBend); var anchor2 = GeomUtils.Interpolate(point2, point3, tBend); // straight segment result.Add(anchor1); // guide point1 -> anchor1 result.Add(point1); result.Add(anchor1); // guide anchor1 -> point2 // bend result.Add(point2); // guide anchor1 -> point2 (more carved ?) result.Add(point2); result.Add(anchor2); // guide point2 -> anchor2 point1 = anchor2; } // last straight segment var lastPoint = anchorPoints[anchorPoints.Count - 1]; result.Add(lastPoint); result.Add(point1); result.Add(lastPoint); return(result); }
public IRect Inflated(double padding) { //if (inflatedCache.ContainsKey(padding)) if (inflatedCache == null) { inflatedCache = GeomUtils.InflateRect(this, padding); } return(inflatedCache); }
public bool Visible(IPoint vertex, IPoint vertex2) { // test for intersection with every box foreach (var rect in this.Boxes) { if (GeomUtils.LineRectIntersection(vertex, vertex2, rect) != null) { return(false); } } return(true); }
public RouteGraphEdge(RouteVertex startVertex, RouteVertex endVertex) { this.StartVertex = startVertex; this.EndVertex = endVertex; this.Length = GeomUtils.LineLenght(startVertex, endVertex); }
/// <summary> /// Initializes the RouteGraph by vertices close to corners of all nodes. /// </summary> /// <param name="boundX">X coordinates of vertices cannot be lower than this value (so that edges stay in boundaries).</param> /// <param name="boundY">Y coordinates of vertices cannot be lower than this value (so that edges stay in boundaries).</param> public static RouteGraph InitializeVertices(IEnumerable <IRect> nodes, IEnumerable <IEdge> edges, int boundX, int boundY) { var graph = new RouteGraph(); // add vertices for node corners foreach (var node in nodes) { graph.Boxes.Add(node); foreach (var vertex in GetRectCorners(node, boxPadding)) { if (vertex.X >= boundX && vertex.Y >= boundY) { graph.Vertices.Add(vertex); } } } // add vertices for egde endpoints foreach (var multiEdgeGroup in edges.GroupBy(edge => GetStartEnd(edge))) { int multiEdgeCount = multiEdgeGroup.Count(); IRect fromRect = multiEdgeGroup.First().From; IRect toRect = multiEdgeGroup.First().To; var sourceCenter = GeomUtils.RectCenter(fromRect); var targetCenter = GeomUtils.RectCenter(toRect); if (Math.Abs(sourceCenter.X - targetCenter.X) > Math.Abs(sourceCenter.Y - targetCenter.Y) || (fromRect == toRect)) { // the line is horizontal double multiEdgeSpanSource = GetMultiEdgeSpan(fromRect.Height, multiEdgeCount, multiEdgeGap); double multiEdgeSpanTarget = GetMultiEdgeSpan(toRect.Height, multiEdgeCount, multiEdgeGap); double originSourceCurrentY = sourceCenter.Y - multiEdgeSpanSource / 2; double originTargetCurrentY = targetCenter.Y - multiEdgeSpanTarget / 2; foreach (var edge in multiEdgeGroup) { Point2D sourceOrigin = new Point2D(sourceCenter.X, originSourceCurrentY); Point2D targetOrigin = new Point2D(targetCenter.X, originTargetCurrentY); // Here user could provide custom edgeStart and edgeEnd // inflate boxes a little so that edgeStart and edgeEnd are a little outside of the box (to prevent floating point errors) if (edge.From == edge.To) { // special case - self edge var edgeStart = new Point2D(fromRect.Left + fromRect.Width + 0.01, originSourceCurrentY); var edgeEnd = new Point2D(fromRect.Left + fromRect.Width / 2, fromRect.Top); graph.AddEdgeEndpointVertices(edge, edgeStart, edgeEnd); } else { var edgeStart = GeomUtils.LineRectIntersection(sourceOrigin, targetOrigin, edge.From.Inflated(1e-3)); var edgeEnd = GeomUtils.LineRectIntersection(sourceOrigin, targetOrigin, edge.To.Inflated(1e-3)); graph.AddEdgeEndpointVertices(edge, edgeStart, edgeEnd); } originSourceCurrentY += multiEdgeSpanSource / (multiEdgeCount - 1); originTargetCurrentY += multiEdgeSpanTarget / (multiEdgeCount - 1); } } else { // the line is vertical double multiEdgeSpanSource = GetMultiEdgeSpan(fromRect.Width, multiEdgeCount, multiEdgeGap); double multiEdgeSpanTarget = GetMultiEdgeSpan(toRect.Width, multiEdgeCount, multiEdgeGap); double originSourceCurrentX = sourceCenter.X - multiEdgeSpanSource / 2; double originTargetCurrentX = targetCenter.X - multiEdgeSpanTarget / 2; foreach (var edge in multiEdgeGroup) { Point2D sourceOrigin = new Point2D(originSourceCurrentX, sourceCenter.Y); Point2D targetOrigin = new Point2D(originTargetCurrentX, targetCenter.Y); // Here user could provide custom edgeStart and edgeEnd // inflate boxes a little so that edgeStart and edgeEnd are a little outside of the box (to prevent floating point errors) var edgeStart = GeomUtils.LineRectIntersection(sourceOrigin, targetOrigin, edge.From.Inflated(1e-3)); var edgeEnd = GeomUtils.LineRectIntersection(sourceOrigin, targetOrigin, edge.To.Inflated(1e-3)); graph.AddEdgeEndpointVertices(edge, edgeStart, edgeEnd); originSourceCurrentX += multiEdgeSpanSource / (multiEdgeCount - 1); originTargetCurrentX += multiEdgeSpanTarget / (multiEdgeCount - 1); } } } return(graph); }