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);
        }