Point GetPointOnTheLeftBoundaryPortConeSide(Point portLocation, ICurve boundaryCurve, bool curveIsClockwise,
                                             double portParam) {
     Point tan = curveIsClockwise
                     ? -boundaryCurve.LeftDerivative(portParam)
                     : boundaryCurve.RightDerivative(portParam);
     return portLocation + tan.Rotate(-EnteringAngleBound);
 }
        Point TakeBoundaryPortOutsideOfItsLoosePolyline(ICurve nodeBoundary, double parameter, Polyline loosePolyline) {
            Point location = nodeBoundary[parameter];
            Point tangent =
                (nodeBoundary.LeftDerivative(parameter).Normalize() +
                 nodeBoundary.RightDerivative(parameter).Normalize()).Normalize();
            if (Point.GetTriangleOrientation(PointInsideOfConvexCurve(nodeBoundary), location, location + tangent) ==
                TriangleOrientation.Counterclockwise)
                tangent = -tangent;

            tangent = tangent.Rotate(Math.PI/2);

            double len = loosePolyline.BoundingBox.Diagonal;
            var ls = new LineSegment(location, location + len*tangent);
            Point p = Curve.GetAllIntersections(ls, loosePolyline, false)[0].IntersectionPoint;

            Point del = tangent*(p - location).Length*0.5;
            //Point del = tangent * this.OffsetForPolylineRelaxing * 2;


            while (true) {
                ls = new LineSegment(location, p + del);
                bool foundIntersectionsOutsideOfSource = false;
                foreach (IntersectionInfo ii in
                    IntersectionsOfLineAndRectangleNodeOverPolyline(ls, ObstacleCalculator.RootOfLooseHierarchy))
                    if (ii.Segment1 != loosePolyline) {
                        del /= 1.5;
                        foundIntersectionsOutsideOfSource = true;
                        break;
                    }
                if (!foundIntersectionsOutsideOfSource)
                    break;
            }

            return ls.End;
        }