/// <summary>
        /// Given a polygon defined by an outer ring with one or more inner rings (holes), return a single list of points representing
        /// a polygon with a hole added to it. The added hole is removed from <paramref name="innerRings"/>.
        /// </summary>
        /// <param name="outerRing">A list of Cartographic points defining the outer polygon.</param>
        /// <param name="innerRings">A list of lists of Cartographic points, each list defining a "hole" in the outer polygon.</param>
        /// <returns>A single list of Cartographic points defining the polygon, including the eliminated inner ring.</returns>
        public static List <Cartographic> EliminateHole(List <Cartographic> outerRing, List <List <Cartographic> > innerRings)
        {
            // Convert from LLA -> XYZ and project points onto a tangent plane to find the mutually visible vertex.
            List <Cartesian> cartesianOuterRing = new List <Cartesian>();

            foreach (Cartographic point in outerRing)
            {
                cartesianOuterRing.Add(Ellipsoid.Wgs84.ToCartesian(point));
            }
            var windingOrder = GetWindingOrder(cartesianOuterRing);
            List <List <Cartesian> > cartesianInnerRings = new List <List <Cartesian> >();

            for (int i = 0; i < innerRings.Count; ++i)
            {
                var ring = innerRings[i];
                List <Cartesian> cartesianInnerRing = new List <Cartesian>();
                foreach (Cartographic point in ring)
                {
                    cartesianInnerRing.Add(Ellipsoid.Wgs84.ToCartesian(point));
                }
                var innerWindingOrder = GetWindingOrder(cartesianInnerRing);
                if (innerWindingOrder == windingOrder)
                {
                    ring.Reverse();
                    cartesianInnerRing.Reverse();
                }
                cartesianInnerRings.Add(cartesianInnerRing);
            }

            EllipsoidTangentPlane tangentPlane = new EllipsoidTangentPlane(Ellipsoid.Wgs84, cartesianOuterRing);

            cartesianOuterRing = (List <Cartesian>)(tangentPlane.ComputePositionsOnPlane(cartesianOuterRing));
            for (int i = 0; i < cartesianInnerRings.Count; i++)
            {
                cartesianInnerRings[i] = (List <Cartesian>)(tangentPlane.ComputePositionsOnPlane(cartesianInnerRings[i]));
            }

            int visibleVertexIndex   = GetMutuallyVisibleVertexIndex(cartesianOuterRing, cartesianInnerRings);
            int innerRingIndex       = GetRightmostRingIndex(cartesianInnerRings);
            int innerRingVertexIndex = GetRightmostVertexIndex(cartesianInnerRings[innerRingIndex]);

            List <Cartographic> innerRing          = innerRings[innerRingIndex];
            List <Cartographic> newPolygonVertices = new List <Cartographic>();

            for (int i = 0; i < outerRing.Count; i++)
            {
                newPolygonVertices.Add(outerRing[i]);
            }

            List <Cartographic> holeVerticesToAdd = new List <Cartographic>();

            // If the rightmost inner vertex is not the starting and ending point of the ring,
            // then some other point is duplicated in the inner ring and should be skipped once.
            if (innerRingVertexIndex != 0)
            {
                for (int j = 0; j <= innerRing.Count; j++)
                {
                    int index = (j + innerRingVertexIndex) % innerRing.Count;
                    if (index != 0)
                    {
                        holeVerticesToAdd.Add(innerRing[index]);
                    }
                }
            }
            else
            {
                for (int j = 0; j < innerRing.Count; j++)
                {
                    holeVerticesToAdd.Add(innerRing[(j + innerRingVertexIndex) % innerRing.Count]);
                }
            }

            int lastVisibleVertexIndex = newPolygonVertices.FindLastIndex(delegate(Cartographic point)
            {
                return(point.Equals(outerRing[visibleVertexIndex]));
            });

            holeVerticesToAdd.Add(outerRing[lastVisibleVertexIndex]);
            newPolygonVertices.InsertRange(lastVisibleVertexIndex + 1, holeVerticesToAdd);
            innerRings.RemoveAt(innerRingIndex);

            return(newPolygonVertices);
        }
        /// <summary>
        /// Given a polygon defined by an outer ring with one or more inner rings (holes), return a single list of points representing
        /// a polygon with a hole added to it. The added hole is removed from <paramref name="innerRings"/>.
        /// </summary>
        /// <param name="outerRing">A list of Cartographic points defining the outer polygon.</param>
        /// <param name="innerRings">A list of lists of Cartographic points, each list defining a "hole" in the outer polygon.</param>
        /// <returns>A single list of Cartographic points defining the polygon, including the eliminated inner ring.</returns>
        public static List<Cartographic> EliminateHole(List<Cartographic> outerRing, List<List<Cartographic>> innerRings)
        {
            // Convert from LLA -> XYZ and project points onto a tangent plane to find the mutually visible vertex.
            List<Cartesian> cartesianOuterRing = new List<Cartesian>();
            foreach (Cartographic point in outerRing)
            {
                cartesianOuterRing.Add(Ellipsoid.Wgs84.ToCartesian(point));
            }
            var windingOrder = GetWindingOrder(cartesianOuterRing);
            List<List<Cartesian>> cartesianInnerRings = new List<List<Cartesian>>();
            for(int i = 0; i < innerRings.Count; ++i)
            {
                var ring = innerRings[i];
                List<Cartesian> cartesianInnerRing = new List<Cartesian>();
                foreach (Cartographic point in ring)
                {
                    cartesianInnerRing.Add(Ellipsoid.Wgs84.ToCartesian(point));
                }
                var innerWindingOrder = GetWindingOrder(cartesianInnerRing);
                if (innerWindingOrder == windingOrder)
                {
                    ring.Reverse();
                    cartesianInnerRing.Reverse();
                }
                cartesianInnerRings.Add(cartesianInnerRing);
            }

            EllipsoidTangentPlane tangentPlane = new EllipsoidTangentPlane(Ellipsoid.Wgs84, cartesianOuterRing);
            cartesianOuterRing = (List<Cartesian>)(tangentPlane.ComputePositionsOnPlane(cartesianOuterRing));
            for (int i = 0; i < cartesianInnerRings.Count; i++)
            {
                cartesianInnerRings[i] = (List<Cartesian>)(tangentPlane.ComputePositionsOnPlane(cartesianInnerRings[i]));
            }

            int visibleVertexIndex = GetMutuallyVisibleVertexIndex(cartesianOuterRing, cartesianInnerRings);
            int innerRingIndex = GetRightmostRingIndex(cartesianInnerRings);
            int innerRingVertexIndex = GetRightmostVertexIndex(cartesianInnerRings[innerRingIndex]);

            List<Cartographic> innerRing = innerRings[innerRingIndex];
            List<Cartographic> newPolygonVertices = new List<Cartographic>();

            for (int i = 0; i < outerRing.Count; i++)
            {
                newPolygonVertices.Add(outerRing[i]);
            }

            List<Cartographic> holeVerticesToAdd = new List<Cartographic>();

            // If the rightmost inner vertex is not the starting and ending point of the ring,
            // then some other point is duplicated in the inner ring and should be skipped once.
            if (innerRingVertexIndex != 0)
            {
                for (int j = 0; j <= innerRing.Count; j++)
                {
                    int index = (j + innerRingVertexIndex) % innerRing.Count;
                    if (index != 0)
                    {
                        holeVerticesToAdd.Add(innerRing[index]);
                    }
                }
            }
            else
            {
                for (int j = 0; j < innerRing.Count; j++)
                {
                    holeVerticesToAdd.Add(innerRing[(j + innerRingVertexIndex) % innerRing.Count]);
                }
            }

            int lastVisibleVertexIndex = newPolygonVertices.FindLastIndex(delegate(Cartographic point)
            {
                return point.Equals(outerRing[visibleVertexIndex]);
            });

            holeVerticesToAdd.Add(outerRing[lastVisibleVertexIndex]);
            newPolygonVertices.InsertRange(lastVisibleVertexIndex + 1, holeVerticesToAdd);
            innerRings.RemoveAt(innerRingIndex);

            return newPolygonVertices;
        }