int FindStaircaseStart(Point[] pts, out bool canHaveStaircase) {
            canHaveStaircase = false;
            if (pts.Length < 5) // At least five points make a staircase
                return -1;
            var segs = new[] {
                                 new SegWithIndex(pts, 0), new SegWithIndex(pts, 1), new SegWithIndex(pts, 2),
                                 new SegWithIndex(pts, 3)
                             };
            int segToReplace = 0;

            for (int i = 0;;) {
                bool canHaveStaircaseAtI;
                if (IsStaircase(pts, i, segs, out canHaveStaircaseAtI)) {
                    canHaveStaircase = true;
                    return i;                    
                }
                canHaveStaircase = canHaveStaircase || canHaveStaircaseAtI;
                i++;
                if (pts.Length < i + 5)// At least five points make a staircase
                    return -1;

                segs[segToReplace] = new SegWithIndex(pts, i + 3);
                segToReplace += 1;
                segToReplace %= 4;
            }
        }
        int FindStaircaseStart(Point[] pts, out bool canHaveStaircase)
        {
            canHaveStaircase = false;
            if (pts.Length < 5) // At least five points make a staircase
            {
                return(-1);
            }
            var segs = new[] {
                new SegWithIndex(pts, 0), new SegWithIndex(pts, 1), new SegWithIndex(pts, 2),
                new SegWithIndex(pts, 3)
            };
            int segToReplace = 0;

            for (int i = 0;;)
            {
                bool canHaveStaircaseAtI;
                if (IsStaircase(pts, i, segs, out canHaveStaircaseAtI))
                {
                    canHaveStaircase = true;
                    return(i);
                }
                canHaveStaircase = canHaveStaircase || canHaveStaircaseAtI;
                i++;
                if (pts.Length < i + 5)// At least five points make a staircase
                {
                    return(-1);
                }

                segs[segToReplace] = new SegWithIndex(pts, i + 3);
                segToReplace      += 1;
                segToReplace      %= 4;
            }
        }
 /// <summary>
 /// ignoring crossing at a
 /// </summary>
 /// <param name="a"></param>
 /// <param name="b"></param>
 /// <param name="segsToIgnore"></param>
 /// <returns></returns>
 bool Crossing(Point a, Point b, SegWithIndex[] segsToIgnore) {
     return IsCrossing(new LineSegment(a, b), segTree, segsToIgnore);
 }
 static Rectangle Rect(SegWithIndex seg) {
     return new Rectangle(seg.Start,seg.End);
 }
 void InsSeg(Point[] pts, int i) {
     var seg = new SegWithIndex(pts, i);
     segTree.Add(Rect(seg), seg);
 }
 void RemoveSeg(SegWithIndex seg) {
     segTree.Remove(Rect(seg), seg);
 }
        bool IsStaircase(Point[] pts, int offset, SegWithIndex[] segsToIgnore, out bool canHaveStaircaseAtI) {
            var a = pts[offset];
            var b = pts[offset + 1];
            var c = pts[offset + 2];
            var d = pts[offset + 3];
            var f = pts[offset + 4];
            canHaveStaircaseAtI = false;
            if (CompassVector.DirectionsFromPointToPoint(a, b) != CompassVector.DirectionsFromPointToPoint(c, d) ||
                CompassVector.DirectionsFromPointToPoint(b, c) != CompassVector.DirectionsFromPointToPoint(d, f))
                return false;

            c = GetFlippedPoint(pts, offset);
            if (IntersectObstacleHierarchy(b, c, d))
                return false;
            canHaveStaircaseAtI = true;
            return !Crossing(b, c, segsToIgnore);
        }
 /// <summary>
 /// ignoring crossing at ls.Start
 /// </summary>
 /// <param name="ls"></param>
 /// <param name="rTree"></param>
 /// <param name="segsToIgnore"></param>
 /// <returns></returns>
 static bool IsCrossing(LineSegment ls, RTree<SegWithIndex> rTree, SegWithIndex[] segsToIgnore) {
     return rTree.GetAllIntersecting(ls.BoundingBox).Where(seg => !segsToIgnore.Contains(seg)).Any();
 }
 static Rectangle Rect(SegWithIndex seg)
 {
     return(new Rectangle(seg.Start, seg.End));
 }
        void InsSeg(Point[] pts, int i)
        {
            var seg = new SegWithIndex(pts, i);

            segTree.Add(Rect(seg), seg);
        }
 void RemoveSeg(SegWithIndex seg)
 {
     segTree.Remove(Rect(seg), seg);
 }