// segments represent an edge where the right side is inside the object and the left side is
        // outside. when objects intersect some segments fall totaly inside the object. (left and right
        // side is in the object). These segments are now redundant so we remove them.
        public void RemoveRedundant()
        {
            int i, j, n_nonhoriz;
            List<Segment2D> lineSegs;
            try
            {
                // collect all horizontal segments and push them to the end, they will be processed in the vertical sweep
                n_nonhoriz = segments.Count;
                for (i = 0; i < n_nonhoriz; i++)
                {
                    while ((i < n_nonhoriz) && (Math.Abs(segments[i].p1.y - segments[i].p2.y) <= Path2D.Epsilon))
                    {
                        Segment2D seg = segments[i];
                        segments.RemoveAt(i);
                        segments.Add(seg);
                        n_nonhoriz--;
                    }
                }
                SegmentBin sbin = new SegmentBin(minx, miny, maxx, maxy, 100);
                sbin.Add(segments);

                // horizontal sweep
                for (i = 0; i < n_nonhoriz; i++)
                {
                    Segment2D seg = segments[i];
                    double y = seg.p1.y + 0.61263546 * (seg.p2.y - seg.p1.y); // arbitrary point between y1 and y2.
                    double u = (y - seg.p1.y) / (seg.p2.y - seg.p1.y);
                    double xpos = seg.p1.x + u * (seg.p2.x - seg.p1.x);
                    int rightCount = 0;
                    int leftCount = 0;
                    /*for (j = 0; j < n_nonhoriz; j++)
                    {
                        if (j == i)
                            continue;
                        UpdateYcrossing(y, xpos, segments[j], ref leftCount, ref rightCount);
                    }*/
                    lineSegs = sbin.GetVbin(y);
                    foreach (Segment2D seg1 in lineSegs)
                    {
                        if (!Object.ReferenceEquals(seg, seg1))
                            UpdateYcrossing(y, xpos, seg1, ref leftCount, ref rightCount);
                    }
                    // mark valid only the segments that one side count is zero and the other non zero
                    if (((leftCount == 0) && (rightCount != 0)) || ((leftCount != 0) && (rightCount == 0)))
                        seg.isValid = true;
                }

                // vertical sweep
                for (i = n_nonhoriz; i < segments.Count; i++)
                {
                    Segment2D seg = segments[i];
                    double x = seg.p1.x + 0.61263546f * (seg.p2.x - seg.p1.x); // arbitrary point between y1 and y2.
                    double u = (x - seg.p1.x) / (seg.p2.x - seg.p1.x);
                    double ypos = seg.p1.y + u * (seg.p2.y - seg.p1.y);
                    int topCount = 0;
                    int botCount = 0;
                    /*for (j = 0; j < segments.Count; j++)
                    {
                        if ((j == i) || (Math.Abs(segments[j].p1.x - segments[j].p2.x) <= Path2D.Epsilon)) // skip vertical lines
                            continue;
                        UpdateXcrossing(x, ypos, segments[j], ref botCount, ref topCount);
                    }*/
                    lineSegs = sbin.GetHbin(x);
                    foreach (Segment2D seg1 in lineSegs)
                    {
                        if (!Object.ReferenceEquals(seg, seg1))
                            UpdateXcrossing(x, ypos, seg1, ref botCount, ref topCount);
                    }

                    // mark valid only the segments that one side count is zero and the other non zero
                    if (((botCount == 0) && (topCount != 0)) || ((botCount != 0) && (topCount == 0)))
                        seg.isValid = true;
                }
            }
            catch (Exception ex)
            {
                DebugLogger.Instance().LogError(ex);
            }
        }
        // segments represent an edge where the right side is inside the object and the left side is
        // outside. when objects intersect some segments fall totaly inside the object. (left and right
        // side is in the object). These segments are now redundant so we remove them.
        public void RemoveRedundant()
        {
            int i, j, n_nonhoriz;
            List <Segment2D> lineSegs;

            try
            {
                // collect all horizontal segments and push them to the end, they will be processed in the vertical sweep
                n_nonhoriz = segments.Count;
                for (i = 0; i < n_nonhoriz; i++)
                {
                    while ((i < n_nonhoriz) && (Math.Abs(segments[i].p1.y - segments[i].p2.y) <= Path2D.Epsilon))
                    {
                        Segment2D seg = segments[i];
                        segments.RemoveAt(i);
                        segments.Add(seg);
                        n_nonhoriz--;
                    }
                }
                SegmentBin sbin = new SegmentBin(minx, miny, maxx, maxy, 100);
                sbin.Add(segments);

                // horizontal sweep
                for (i = 0; i < n_nonhoriz; i++)
                {
                    Segment2D seg        = segments[i];
                    double    y          = seg.p1.y + 0.61263546 * (seg.p2.y - seg.p1.y); // arbitrary point between y1 and y2.
                    double    u          = (y - seg.p1.y) / (seg.p2.y - seg.p1.y);
                    double    xpos       = seg.p1.x + u * (seg.p2.x - seg.p1.x);
                    int       rightCount = 0;
                    int       leftCount  = 0;

                    /*for (j = 0; j < n_nonhoriz; j++)
                     * {
                     *  if (j == i)
                     *      continue;
                     *  UpdateYcrossing(y, xpos, segments[j], ref leftCount, ref rightCount);
                     * }*/
                    lineSegs = sbin.GetVbin(y);
                    foreach (Segment2D seg1 in lineSegs)
                    {
                        if (!Object.ReferenceEquals(seg, seg1))
                        {
                            UpdateYcrossing(y, xpos, seg1, ref leftCount, ref rightCount);
                        }
                    }
                    // mark valid only the segments that one side count is zero and the other non zero
                    if (((leftCount == 0) && (rightCount != 0)) || ((leftCount != 0) && (rightCount == 0)))
                    {
                        seg.isValid = true;
                    }
                }

                // vertical sweep
                for (i = n_nonhoriz; i < segments.Count; i++)
                {
                    Segment2D seg      = segments[i];
                    double    x        = seg.p1.x + 0.61263546f * (seg.p2.x - seg.p1.x); // arbitrary point between y1 and y2.
                    double    u        = (x - seg.p1.x) / (seg.p2.x - seg.p1.x);
                    double    ypos     = seg.p1.y + u * (seg.p2.y - seg.p1.y);
                    int       topCount = 0;
                    int       botCount = 0;

                    /*for (j = 0; j < segments.Count; j++)
                     * {
                     *  if ((j == i) || (Math.Abs(segments[j].p1.x - segments[j].p2.x) <= Path2D.Epsilon)) // skip vertical lines
                     *      continue;
                     *  UpdateXcrossing(x, ypos, segments[j], ref botCount, ref topCount);
                     * }*/
                    lineSegs = sbin.GetHbin(x);
                    foreach (Segment2D seg1 in lineSegs)
                    {
                        if (!Object.ReferenceEquals(seg, seg1))
                        {
                            UpdateXcrossing(x, ypos, seg1, ref botCount, ref topCount);
                        }
                    }

                    // mark valid only the segments that one side count is zero and the other non zero
                    if (((botCount == 0) && (topCount != 0)) || ((botCount != 0) && (topCount == 0)))
                    {
                        seg.isValid = true;
                    }
                }
            }
            catch (Exception ex)
            {
                DebugLogger.Instance().LogError(ex);
            }
        }