private Polygon CreateKmlPolygon(IPolygon polygon)
        {
            var kmlPolygon = new Polygon();
            var ring       = new LinearRing {
                Coordinates = new CoordinateCollection()
            };

            kmlPolygon.OuterBoundary = new OuterBoundary {
                LinearRing = ring
            };

            foreach (var coordinate in polygon.ExteriorRing.Coordinates)
            {
                ring.Coordinates.Add(new Vector(coordinate.Y, coordinate.X));
            }

            foreach (var interiorRing in polygon.InteriorRings)
            {
                var innerBoundary = new InnerBoundary();
                kmlPolygon.AddInnerBoundary(innerBoundary);

                ring = new LinearRing {
                    Coordinates = new CoordinateCollection()
                };

                innerBoundary.LinearRing = ring;

                foreach (var coordinate in interiorRing.Coordinates)
                {
                    ring.Coordinates.Add(new Vector(coordinate.Y, coordinate.X));
                }
            }

            return(kmlPolygon);
        }
        private Geometry GetKml(TPolygon polygon)
        {
            if (polygon.Rings.Count == 0)
            {
                return(null);
            }
            var outher = polygon.GetOuterBoundary();

            if (outher == null)
            {
                return(GetKml(polygon.AsCollection()));
            }
            var outherKml = new OuterBoundary {
                LinearRing = GetRingKml(outher)
            };
            var kml = new Polygon {
                OuterBoundary = outherKml
            };

            foreach (var ring in polygon.Rings)
            {
                if (ring == outher)
                {
                    continue;
                }
                var inner = new InnerBoundary()
                {
                    LinearRing = GetRingKml(ring)
                };
                var _ = kml.InnerBoundary.Append(inner);
            }
            return(kml);
        }
        /// <summary>
        /// Adds a vertex to current triangulation using incremental algorithm Bowyer-Watson
        /// algorithm if vertex is completely inside triangulation otherwise
        /// creates triangles on visible boundary and restores delaunay property.
        /// </summary>
        /// <param name="vertexIndex">Vertex index.</param>
        private bool AddVertex(int vertexIndex)
        {
            // First: locate the given vertex.
            // Determine whether it's in the specific triangle or
            // lies outside of triangulation.
            var vertex = InnerVertices[vertexIndex].Pos;
            var result = LocateClosestTriangle(vertex, out var halfEdge);

            // Check special cases:
            // Same vertex already exists:
            if (result == LocationResult.SameVertex)
            {
                // Shouldn't insert vertex
                int sameVertexIndex = -1;
                for (int i = 0; i < Vertices.Count; i++)
                {
                    if (i != vertexIndex && Vertices[i].Pos == vertex)
                    {
                        sameVertexIndex = i;
                        break;
                    }
                }
                if (sameVertexIndex >= 0)
                {
                    return(false);
                }
                // otherwise it can be bounding figure vertex.
                if (!BelongsToBoundingFigure(vertex, out var bfvi) || halfEdge.Origin != -bfvi)
                {
                    return(false);
                }
                foreach (var incidentEdge in IncidentEdges(halfEdge))
                {
                    incidentEdge.Origin = vertexIndex;
                }
            }
            else if (result == LocationResult.OnEdge)
            {
                // Should split edge
                var prev = halfEdge.Origin;
                var next = halfEdge.Next.Origin;
                SplitEdge(vertexIndex, halfEdge);
                if (InnerBoundary.Contains(prev) && InnerBoundary.Next(prev) == next)
                {
                    // Then we splitted boundary edge.
                    InnerBoundary.Insert(prev, vertexIndex);
                }
                else if (InnerBoundary.Contains(next) && InnerBoundary.Next(next) == prev)
                {
                    InnerBoundary.Insert(next, vertexIndex);
                }
            }
            else if (result == LocationResult.InsideTriangle)
            {
                // Boywer-Watson algorithm
                Root = BowyerWatson(vertexIndex, halfEdge);
            }
            else
            {
                // Find boundary of triangulation that is visible from given vertex.
                // Build triangles on the sides of the visible boundary.
                // Use flip algorithm to restore delaunay property.
                var visibleBoundary = GetVisibleBoundary(vertexIndex, halfEdge);
                // Should probably triangulate only leftmost\rightmost\closest chain
                // of visible edges (for better UE).
                var      edgesToCheck            = new List <HalfEdge>(visibleBoundary[0].Count * 2);
                HalfEdge lastConstructedTriangle = null;
                foreach (var edge in visibleBoundary[0])
                {
                    var twin = new HalfEdge(edge.Next.Origin)
                    {
                        Next = new HalfEdge(edge.Origin)
                        {
                            Next = new HalfEdge(vertexIndex),
                        }
                    };
                    twin.Prev.Next = twin;
                    edge.TwinWith(twin);
                    lastConstructedTriangle?.Prev.TwinWith(twin.Next);
                    lastConstructedTriangle = twin;
                    edgesToCheck.Add(edge);
                    edgesToCheck.Add(twin.Next);
                }
                RestoreDelaunayProperty(edgesToCheck);
            }
            return(true);
        }