public Point2DList(Point2DList l)
        {
            int numPoints = l.Count;

            for (int i = 0; i < numPoints; ++i)
            {
                mPoints.Add(l[i]);
            }
            mBoundingBox.Set(l.BoundingBox);
            mEpsilon      = l.Epsilon;
            mWindingOrder = l.WindingOrder;
        }
 public virtual void AddRange(Point2DList l)
 {
     AddRange(l.mPoints.GetEnumerator(), l.WindingOrder);
 }
        public void MergeParallelEdges(double tolerance)
        {
            if (Count <= 3)
            {
                return;
            }

            bool[] mergeMe      = new bool[Count];
            int    newNVertices = Count;

            for (int i = 0; i < Count; ++i)
            {
                int lower  = (i == 0) ? (Count - 1) : (i - 1);
                int middle = i;
                int upper  = (i == Count - 1) ? (0) : (i + 1);

                double dx0   = this[middle].X - this[lower].X;
                double dy0   = this[middle].Y - this[lower].Y;
                double dx1   = this[upper].Y - this[middle].X;
                double dy1   = this[upper].Y - this[middle].Y;
                double norm0 = Math.Sqrt(dx0 * dx0 + dy0 * dy0);
                double norm1 = Math.Sqrt(dx1 * dx1 + dy1 * dy1);

                if (!(norm0 > 0.0 && norm1 > 0.0) && newNVertices > 3)
                {
                    mergeMe[i] = true;
                    --newNVertices;
                }

                dx0 /= norm0;
                dy0 /= norm0;
                dx1 /= norm1;
                dy1 /= norm1;
                double cross = dx0 * dy1 - dx1 * dy0;
                double dot   = dx0 * dx1 + dy0 * dy1;

                if (Math.Abs(cross) < tolerance && dot > 0 && newNVertices > 3)
                {
                    mergeMe[i] = true;
                    --newNVertices;
                }
                else
                {
                    mergeMe[i] = false;
                }
            }

            if (newNVertices == Count || newNVertices == 0)
            {
                return;
            }

            int currIndex = 0;

            Point2DList oldVertices = new Point2DList(this);

            Clear();

            for (int i = 0; i < oldVertices.Count; ++i)
            {
                if (mergeMe[i] || newNVertices == 0 || currIndex == newNVertices)
                {
                    continue;
                }

                if (currIndex >= newNVertices)
                {
                    throw new Exception("Point2DList::MergeParallelEdges - currIndex[ " + currIndex.ToString() + "] >= newNVertices[" + newNVertices + "]");
                }

                mPoints.Add(oldVertices[i]);
                mBoundingBox.AddPoint(oldVertices[i]);
                ++currIndex;
            }
            mWindingOrder = CalculateWindingOrder();
            mEpsilon      = CalculateEpsilon();
        }
        public PolygonError CheckPolygon()
        {
            PolygonError error = PolygonError.None;

            if (Count < 3 || Count > Point2DList.kMaxPolygonVertices)
            {
                error |= PolygonError.NotEnoughVertices;
                return(error);
            }
            if (IsDegenerate())
            {
                error |= PolygonError.Degenerate;
            }

            if (!IsSimple())
            {
                error |= PolygonError.NotSimple;
            }

            if (GetArea() < MathUtil.EPSILON)
            {
                error |= PolygonError.AreaTooSmall;
            }

            if ((error & PolygonError.NotSimple) != PolygonError.NotSimple)
            {
                bool             bReversed            = false;
                WindingOrderType expectedWindingOrder = WindingOrderType.CCW;
                WindingOrderType reverseWindingOrder  = WindingOrderType.CW;
                if (WindingOrder == reverseWindingOrder)
                {
                    WindingOrder = expectedWindingOrder;
                    bReversed    = true;
                }

                Point2D[]   normals  = new Point2D[Count];
                Point2DList vertices = new Point2DList(Count);
                for (int i = 0; i < Count; ++i)
                {
                    vertices.Add(new Point2D(this[i].X, this[i].Y));
                    int     i1   = i;
                    int     i2   = NextIndex(i);
                    Point2D edge = new Point2D(this[i2].X - this[i1].X, this[i2].Y - this[i1].Y);
                    normals[i] = Point2D.Perpendicular(edge, 1.0);
                    normals[i].Normalize();
                }

                for (int i = 0; i < Count; ++i)
                {
                    int iminus = PreviousIndex(i);

                    double cross = Point2D.Cross(normals[iminus], normals[i]);
                    cross = MathUtil.Clamp(cross, -1.0f, 1.0f);
                    float angle = (float)Math.Asin(cross);
                    if (Math.Abs(angle) <= Point2DList.kAngularSlop)
                    {
                        error |= PolygonError.SidesTooCloseToParallel;
                        break;
                    }
                }

                if (bReversed)
                {
                    WindingOrder = reverseWindingOrder;
                }
            }

            return(error);
        }