bool StickingSegmentDoesNotIntersectTightObstacles(RelaxedPolylinePoint relaxedPoint) {
     return
         !LineIntersectsTightObstacles(new LineSegment(relaxedPoint.PolylinePoint.Point,
                                                       relaxedPoint.Prev.PolylinePoint.Point)) && (
                                                                                                      (relaxedPoint
                                                                                                           .Next ==
                                                                                                       null ||
                                                                                                       !LineIntersectsTightObstacles
                                                                                                            (new LineSegment
                                                                                                                 (relaxedPoint
                                                                                                                      .
                                                                                                                      PolylinePoint
                                                                                                                      .
                                                                                                                      Point,
                                                                                                                  relaxedPoint
                                                                                                                      .
                                                                                                                      Next
                                                                                                                      .
                                                                                                                      PolylinePoint
                                                                                                                      .
                                                                                                                      Point))));
 }
        static void SetRelaxedPointLocation(double offset, RelaxedPolylinePoint relaxedPoint) {
            bool leftTurn = Point.GetTriangleOrientation(relaxedPoint.Next.OriginalPosition,
                                                         relaxedPoint.OriginalPosition,
                                                         relaxedPoint.Prev.OriginalPosition) ==
                            TriangleOrientation.Counterclockwise;
            Point v =
                ((relaxedPoint.Next.OriginalPosition - relaxedPoint.Prev.OriginalPosition).Normalize() * offset).Rotate(
                    Math.PI / 2);

            if (!leftTurn)
                v = -v;
            relaxedPoint.PolylinePoint.Point = relaxedPoint.OriginalPosition + v;
        }
        bool RelaxWithGivenOffset(double offset, RelaxedPolylinePoint relaxedPoint) {
            SetRelaxedPointLocation(offset, relaxedPoint);
#if TEST_MSAGL
            //ShowPolylineAndObstacles();
#endif
            if (StickingSegmentDoesNotIntersectTightObstacles(relaxedPoint))
                return true;
            PullCloserRelaxedPoint(relaxedPoint.Prev);
            return false;
        }
 static void PullCloserRelaxedPoint(RelaxedPolylinePoint relaxedPolylinePoint) {
     relaxedPolylinePoint.PolylinePoint.Point = 0.2 * relaxedPolylinePoint.OriginalPosition +
                                                0.8 * relaxedPolylinePoint.PolylinePoint.Point;
 }
 void RelaxPolylinePoint(RelaxedPolylinePoint relaxedPoint) {
     for (double d = OffsetForPolylineRelaxing; !RelaxWithGivenOffset(d, relaxedPoint); d /= 2) {
     }
 }
 static RelaxedPolylinePoint CreateRelaxedPolylinePoints(Polyline polyline) {
     PolylinePoint p = polyline.StartPoint;
     var ret = new RelaxedPolylinePoint(p, p.Point);
     RelaxedPolylinePoint currentRelaxed = ret;
     while (p.Next != null) {
         p = p.Next;
         var r = new RelaxedPolylinePoint(p, p.Point) { Prev = currentRelaxed };
         currentRelaxed.Next = r;
         currentRelaxed = r;
     }
     return ret;
 }
 bool StickingSegmentDoesNotIntersectTightObstacles(RelaxedPolylinePoint relaxedPoint) {
     return
         !PolylineSegmentIntersectsTightHierarchy(relaxedPoint.PolylinePoint.Point,
                                                  relaxedPoint.Prev.PolylinePoint.Point) &&
         (relaxedPoint.Next == null ||
          !PolylineSegmentIntersectsTightHierarchy(relaxedPoint.PolylinePoint.Point,
                                                   relaxedPoint.Next.PolylinePoint.Point));
 }
        bool RelaxWithGivenOffset(double offset, RelaxedPolylinePoint relaxedPoint) {
            Debug.Assert(offset > ApproximateComparer.DistanceEpsilon); //otherwise we are cycling infinitely here
            SetRelaxedPointLocation(offset, relaxedPoint);

            if (StickingSegmentDoesNotIntersectTightObstacles(relaxedPoint)) {
                return true;
            }
            PullCloserRelaxedPoint(relaxedPoint.Prev);
            return false;
        }
 void RelaxPolylinePoint(RelaxedPolylinePoint relaxedPoint) {
     if (relaxedPoint.PolylinePoint.Prev.Prev == null && SourcePort is CurvePort &&
         relaxedPoint.PolylinePoint.Polyline != SourceLoosePolyline)
         return;
     if (relaxedPoint.PolylinePoint.Next.Next == null && TargetPort is CurvePort &&
         relaxedPoint.PolylinePoint.Polyline != TargetLoosePolyline)
         return;
     for (double d = OffsetForPolylineRelaxing;
          d > ApproximateComparer.DistanceEpsilon && !RelaxWithGivenOffset(d, relaxedPoint);
          d /= 2) {
     }
 }