//void ReducePolyline() {
        //    for (PolylinePoint pp = this.Polyline.StartPoint.Next; pp.Next != null && pp.Next.Next != null;pp=pp.Next )
        //        pp = TryToRemoveOrDiminishSegment(pp, pp.Next);
        //}

        //PolylinePoint TryToRemoveOrDiminishSegment(PolylinePoint pp, PolylinePoint polylinePoint) {
        //    TriangleOrientation orientation = Point.GetTriangleOrientation(pp.Prev.Point, pp.Point, pp.Next.Point);
        //    if (orientation == Point.GetTriangleOrientation(pp.Point, pp.Next.Point, pp.Next.Next.Point)) {
        //        Point x;
        //        if (Point.LineLineIntersection(pp.Prev.Point, pp.Point, pp.Next.Point, pp.Next.Next.Point, out x)) {
        //            if (orientation == Point.GetTriangleOrientation(pp.Point, x, pp.Next.Point)) {
        //                if (!LineIntersectsTightObstacles(pp.Prev.Point, x) && !LineIntersectsTightObstacles(x, pp.Next.Next.Point)) {
        //                    PolylinePoint px = new PolylinePoint(x);
        //                    //inserting px instead of pp and pp.Next
        //                    px.Prev = pp.Prev;
        //                    pp.Prev.Next = px;
        //                    px.Next = pp.Next.Next;
        //                    pp.Next.Next.Prev = px;
        //                    return px.Prev;
        //                } else {
        //                    for (double k = 0.5; k > 0.01; k /= 2) {
        //                        Point a = pp.Point * (1 - k) + x * k;
        //                        Point b = pp.Next.Point * (1 - k) + x * k;

        //                        if (!LineIntersectsTightObstacles(pp.Point, a) &&
        //                            !LineIntersectsTightObstacles(a, b) &&
        //                            !LineIntersectsTightObstacles(b, pp.Next.Point)) {
        //                            pp.Point = a;
        //                            pp.Next.Point = b;
        //                            break;
        //                        }
        //                    }
        //                }
        //            }
        //        }
        //    }
        //    return pp;
        //}


        //bool LineIntersectsTightObstacles(Point point, Point x) {
        //    return LineIntersectsTightObstacles(new LineSegment(point, x));
        //}
#if TEST_MSAGL
        //private void ShowPolylineAndObstaclesWithGraph() {
        //    List<ICurve> ls = new List<ICurve>();
        //    foreach (Polyline poly in this.obstacleCalculator.TightObstacles)
        //        ls.Add(poly);
        //    foreach (Polyline poly in this.obstacleCalculator.LooseObstacles)
        //        ls.Add(poly);
        //    AddVisibilityGraph(ls);
        //    ls.Add(Polyline);
        //    SugiyamaLayoutSettings.Show(ls.ToArray());
        //}
#endif
        //pull the polyline out from the corners
        void RelaxPolyline()
        {
            RelaxedPolylinePoint relaxedPolylinePoint = CreateRelaxedPolylinePoints(Polyline);

            //ShowPolylineAndObstacles();
            for (relaxedPolylinePoint = relaxedPolylinePoint.Next;
                 relaxedPolylinePoint.Next != null;
                 relaxedPolylinePoint = relaxedPolylinePoint.Next)
            {
                RelaxPolylinePoint(relaxedPolylinePoint);
            }
        }
        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 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;
        }
        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
         (!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 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)
     {
     }
 }