static void RouteClusterParentInEdges(List<Edge> inParentEdges, EdgeRoutingSettings edgeRoutingSettings, Cluster cluster, double padding) { foreach (var e in cluster.InEdges.Where(e => IsDescendant(e.Source, cluster))) { double ePadding = Math.Max(padding, 1.5*ArrowlengthAtTarget(e)); var hookPort = e.TargetPort as HookUpAnywhereFromInsidePort; if (hookPort == null) e.TargetPort = hookPort = new HookUpAnywhereFromInsidePort(() => cluster.BoundaryCurve); hookPort.HookSize = ePadding; e.Curve = StraightLineEdges.CreateLoop(e.Source.BoundingBox, cluster.BoundingBox, ePadding, false); Arrowheads.TrimSplineAndCalculateArrowheads(e, e.Curve, false, edgeRoutingSettings.KeepOriginalSpline); inParentEdges.Add(e); } }
double GetIdealDistanceBetweenHookUpAnywherePortAndPort(HookUpAnywhereFromInsidePort hookPort, Port port) { var poly = hookPort.LoosePolyline; var point = port.Location; var closestPar = poly.ClosestParameter(point); return (point - poly[closestPar]).Length; }
void FixLastPolylinePointForAnywherePort(HookUpAnywhereFromInsidePort port) { while (true) { PolylinePoint lastPointInside = GetLastPointInsideOfCurveOnPolyline(port.Curve); lastPointInside.Next.Next = null; _polyline.EndPoint=lastPointInside.Next; var dir = lastPointInside.Next.Point - lastPointInside.Point; dir = dir.Normalize()*port.Curve.BoundingBox.Diagonal; //make it a long vector var dir0 = dir.Rotate(-port.AdjustmentAngle); var dir1 = dir.Rotate(port.AdjustmentAngle); var rx=Curve.CurveCurveIntersectionOne(port.Curve, new LineSegment(lastPointInside.Point, lastPointInside.Point+dir0), true); var lx=Curve.CurveCurveIntersectionOne(port.Curve, new LineSegment(lastPointInside.Point, lastPointInside.Point+dir1), true); if (rx == null || lx == null) return; //this.ShowPolylineAndObstacles(Polyline, new LineSegment(lastPointInside.Point, lastPointInside.Point+dir0), new LineSegment(lastPointInside.Point, rerPoint+dir1), port.Curve); var trimmedCurve = GetTrimmedCurveForHookingUpAnywhere(port.Curve, lastPointInside, rx, lx); var newLastPoint = trimmedCurve[trimmedCurve.ClosestParameter(lastPointInside.Point)]; if (!LineAvoidsTightHierarchy(new LineSegment(lastPointInside.Point, newLastPoint), SourceTightPolyline, null)) { var xx=Curve.CurveCurveIntersectionOne(port.Curve, new LineSegment(lastPointInside.Point, lastPointInside.Next.Point), false); if (xx == null) return; //this.ShowPolylineAndObstacles(Polyline, port.Curve); _polyline.EndPoint.Point = xx.IntersectionPoint; break; } _polyline.EndPoint.Point = newLastPoint; if (lastPointInside.Prev == null || !TryShortcutPolyPoint(lastPointInside.Prev)) break; } }
void ExtendPolyline(Point tangentAtIntersection, IntersectionInfo x, Point polylineTangent, HookUpAnywhereFromInsidePort port) { var normal=tangentAtIntersection.Rotate(Math.PI/2); if(normal*polylineTangent<0) normal=-normal; var pointBeforeLast = x.IntersectionPoint + normal * port.HookSize; Point pointAfterX; if (!Point.LineLineIntersection(pointBeforeLast, pointBeforeLast+tangentAtIntersection, _polyline.End, _polyline.End+polylineTangent, out pointAfterX)) return; _polyline.AddPoint(pointAfterX); _polyline.AddPoint(pointBeforeLast); _polyline.AddPoint(x.IntersectionPoint); }
void BuildHook(HookUpAnywhereFromInsidePort port) { var curve = port.Curve; //creating a hook var ellipse = new Ellipse(port.HookSize, port.HookSize, _polyline.End); var intersections = Curve.GetAllIntersections(curve, ellipse, true).ToArray(); Debug.Assert(intersections.Length == 2); if (Point.GetTriangleOrientation(intersections[0].IntersectionPoint, _polyline.End, _polyline.EndPoint.Prev.Point) == TriangleOrientation.Counterclockwise) intersections.Reverse(); //so the [0] point is to the left of the Polyline var polylineTangent = (_polyline.End - _polyline.EndPoint.Prev.Point).Normalize(); var tan0 = curve.Derivative(intersections[0].Par0).Normalize(); var prj0 = tan0 * polylineTangent; if (Math.Abs(prj0) < 0.2) ExtendPolyline(tan0, intersections[0], polylineTangent, port); else { var tan1 = curve.Derivative(intersections[1].Par0).Normalize(); var prj1 = tan1 * polylineTangent; if (prj1 < prj0) ExtendPolyline(tan1, intersections[1], polylineTangent, port); else ExtendPolyline(tan0, intersections[0], polylineTangent, port); } }
ICurve RouteFromFloatingPortToAnywherePort(Polyline targetLoosePoly, bool smooth, out SmoothedPolyline smoothedPolyline, HookUpAnywhereFromInsidePort port) { if (!port.Curve.BoundingBox.Contains(sourcePort.Location)) { smoothedPolyline = null; return null; } _sourceVisibilityVertex = GetVertex(sourcePort.Location); _polyline = GetShortestPolylineToMulitpleTargets(SourceVisibilityVertex, Targets(targetLoosePoly)); if (_polyline == null) { smoothedPolyline = null; return null; } if (UseSpanner) TryShortcutPolyline(); RelaxPolyline(); FixLastPolylinePointForAnywherePort(port); if (port.HookSize > 0) BuildHook(port); return SmoothCornersAndReturnCurve(smooth, out smoothedPolyline); }