public C5.HashSet <EventPoint> DeleteMin() // Pobierz i zwróć najmniejszy element kolejki
        {
            if (isEmpty())
            {
                throw new Exception("Kolejka jest pusta");
            }

            var entry = _events.DeleteMin();
            var hs    = new C5.HashSet <EventPoint>();

            hs.AddAll(entry.Value);
            return(hs);
        }
    /// <summary>
    /// Optimizes navmesh by deleting some triangles
    /// </summary>
    /// <param name="itm"></param>
    public IEnumerator OptimizeMesh()
    {
        C5.HashSet <Vector3>  open  = new C5.HashSet <Vector3>();
        C5.HashSet <Triangle> openT = new C5.HashSet <Triangle>();
        open.AddAll(vertex2Triangle.Keys);

        while (!open.IsEmpty)    //loop through all vertices

        {
            Vector3 current = open.Pop();

            if (vertex2Triangle[current].Count < 3) //if less than 3, they cannot form a "circle"
            {
                continue;
            }

            openT.Clear();
            openT.AddAll(vertex2Triangle[current]);

            //Debug.Log("Opening " + current);

            //start at arbitrary triangle
            C5.IList <Triangle> circle = new C5.ArrayList <Triangle>();
            circle.Add(openT.Pop());

            //find connected circle
            while (openT.Count > 0)
            {
                Triangle[] circleElement = openT.Intersect(triangleIncidence[circle.Last]).ToArray();
                if (circleElement.Length < 1) //no candidate - break
                {
                    break;
                }
                circle.Add(circleElement[0]);

                openT.Remove(circle.Last);
            }
            if (openT.Count == 0 && triangleIncidence[circle.Last].Contains(circle.First))
            {
                //Debug.Log( "Unbroken: "+current );
                //check height differences
                bool isFlatEnough = true;
                foreach (Triangle trg in vertex2Triangle[current])
                {
                    foreach (Vector3 vct in trg.vertices)
                    {
                        if (Mathf.Abs(vct.y - current.y) > maxHeightDifference)
                        {
                            isFlatEnough = false;
                        }
                    }
                }
                if (!isFlatEnough)
                {
                    continue;
                }

                ArrayList <Vector3> vctList = new ArrayList <Vector3>();

                //remove old triangles
                foreach (Triangle trg in circle)   //ToArray() is to create a buffer (to prevent concurrent modification)
                {
                    RemoveTriangle(trg);
                    for (int i = 0; i < 3; i++)
                    {
                        //find the CURRENT vertex - the one that is beeing removed
                        if (trg.vertices[i] == current)
                        {
                            //add the NEXT to the list
                            vctList.Add(trg.vertices[(i + 1) % 3]);
                        }
                    }
                }

                if (Outline.IsClockwise(vctList))
                {
                    vctList.Reverse();
                }
                //build new triangles and add them
                foreach (IEnumerable <int> newTriangles in Utils.TriangulatePolygon(vctList, Enumerable.Range(0, vctList.Count)).Chunks(3))
                {
                    Triangle newTriag = new Triangle(newTriangles.Select(x => vctList[x]).ToArray());
                    AddTriangleByReference(newTriag);
                }

                //reopen used vertices
                //open.AddAll(vctList); - maybe not necessary????
                //yield return new WaitForSeconds(1);
                yield return(null);
            }
        }
    }
    public IEnumerable <Mesh> ExtractMeshes()
    {
        List <Mesh> meshes = new List <Mesh>();

        C5.HashSet <Triangle> untouched = new C5.HashSet <Triangle>();
        untouched.AddAll(triangleIncidence.Keys);

        Queue <Triangle> open = new Queue <Triangle>();



        //the mesh that is beeing built
        List <Vector3>            vertices      = new List <Vector3>();
        Dictionary <Vector3, int> vertexToIndex = new Dictionary <Vector3, int>();
        List <int> indices = new List <int>();

        while (!untouched.IsEmpty)
        {
            if (open.Count == 0)  //empty - open on a new slot
            {
                open.Enqueue(untouched.First());
                untouched.Remove(open.First());
            }

            if (vertices.Count > 60000)  //too many - split meshes
            {
                Mesh msh = new Mesh();
                msh.vertices  = vertices.ToArray();
                msh.triangles = indices.ToArray();
                meshes.Add(msh);
                vertices.Clear();
                vertexToIndex.Clear();
                indices.Clear();
            }

            //one step of BFS
            Triangle current = open.Dequeue();
            foreach (Triangle expand in triangleIncidence[current])
            {
                if (untouched.Contains(expand))
                {
                    open.Enqueue(expand);
                    untouched.Remove(expand);
                }
            }
            //add to mesh
            for (int i = 0; i < 3; i++)
            {
                if (vertexToIndex.ContainsKey(current.vertices[i]))
                {
                    indices.Add(vertexToIndex[current.vertices[i]]);
                }
                else
                {
                    vertices.Add(current.vertices[i]);
                    vertexToIndex[current.vertices[i]] = vertices.Count - 1;
                    indices.Add(vertices.Count - 1);
                }
            }
        }

        //buuild last mesh
        Mesh msh2 = new Mesh();

        msh2.vertices  = vertices.ToArray();
        msh2.triangles = indices.ToArray();
        meshes.Add(msh2);

        return(meshes);
    }