public PVector CalculateVertexForce(Vertex v)
        {
            PVector resultF = new PVector();
            foreach (Edge e in v.edges)
            { // смятаме пружинните сили(на ребрата) - привличат
                Vertex other = e.source == v ? e.destination : e.source;

                if (float.IsNaN(other.x) || float.IsNaN(other.y) || float.IsNaN(v.x) || float.IsNaN(v.y)) continue;

                double dx = v.x - other.x;
                double dy = v.y - other.y;

                resultF.Add(GetAttractionForce(dx, dy));
            }

            foreach (Vertex vo in graph.vertices)
            { // електрични сили
                if (v == vo) continue;

                if (float.IsNaN(vo.x) || float.IsNaN(vo.y) || float.IsNaN(v.x) || float.IsNaN(v.y)) continue;

                double dx = v.x - vo.x;
                double dy = v.y - vo.y;

                resultF.Add(GetRepulsionForce(dx, dy));
            }
            return resultF;
        }
        public UiVertexMenu(Vertex v, Graph g, float x, float y)
        {
            visible = true;
            children = new List<UiComponent>();

            X = (int)x;
            Y = (int)y;

            this.v = v;
            graph = g;
            topMenu = new UiVerticalMenu();
            topMenu.AddItem("Премахни връх", RemoveVertex);

            topMenu.X = 3;
            topMenu.Y = 3;

            Width = topMenu.Width + 6;
            Height = topMenu.Height + 6;

            AddChild(topMenu);

            int yp = topMenu.Height + 6; 

            if(v.edges.Count > 0)
            { // изброява всички ребра
                UiLabel label = new UiLabel("Премахни ребро:", GraphicScheme.font1);
                label.X = 3;
                label.Y = yp;
                yp += label.Height + 3;
                AddChild(label);

                bottomMenu = new UiVerticalMenu();

                bottomMenu.X = 3;
                bottomMenu.Y = yp;

                bottomMenu.Width = topMenu.Width;

                Edge e;
                Vertex vo;                

                for (int i = 0; i < v.edges.Count; i++)
                {
                    e = v.edges[i];
                    vo = e.source == v ? e.destination : e.source;
                    dict.Add(bottomMenu.AddItem(vo.id.ToString(), RemoveEdge).id, e);
                }

                AddChild(bottomMenu);
                yp += bottomMenu.Height;

                Height = yp + 3;
            }
            
        }
        public void SimulateVertex(Vertex v)
        {
            foreach(Edge e in v.edges)
            { // смятаме пружинните сили(на ребрата) - привличат
                Vertex other = e.source == v ? e.destination : e.source;

                float dist = CalculateDistance(v, other);
                float ndist = dist < 0 ? dist*-1 : dist;
                float f = -CalculateSpringForce(ndist); // обратен знак -> привлича

                float dx = v.x - other.x;
                float dy = v.y - other.y;

                float fSin = dy / dist;
                float fCos = dx / dist;

                v.velocity.Add(new PVector(f * fCos, f * fSin));
            }

            foreach(Vertex vo in graph.vertices)
            { // електрични сили
                if (v == vo) continue;

                float dist = CalculateDistance(v, vo);
                float ndist = dist < 0 ? dist * -1 : dist;
                float f = CalculateElectricForce(ndist);

                float dx = v.x - vo.x;
                float dy = v.y - vo.y;

                float fSin = dy / dist;
                float fCos = dx / dist;

                v.velocity.Add(new PVector(f * fCos, f * fSin));
            }
        }
        void window_MouseButtonPressed(object sender, MouseButtonEventArgs e)
        {
            Vector2i mousePos = Mouse.GetPosition(window);
            Vector2f pos = ToGlobalCoords(Mouse.GetPosition(window));

            Vertex v = GetVertexAt(pos);
            Edge edge = GetEdgeAt(pos);
            if (e.Button == Mouse.Button.Left && inputEdge != null) FinishWeight();
            else if (e.Button == Mouse.Button.Left && inputEdge == null)
            {
                rmbMenu.visible = false;
                if (activeVertexMenu != null)
                {
                    activeVertexMenu.Remove();
                    activeVertexMenu = null;
                }
                if(activeEdgeMenu != null)
                {
                    activeEdgeMenu.Remove();
                    activeEdgeMenu = null;
                }
                if(!gui.ProcessMouseClick(mousePos) && addEdgeEnabled)
                {                  
                    if(v!=null)
                    {
                        if (lastClickedVertex != null && lastClickedVertex != v)
                        {
                            Edge newEdge = activeGraph.AddEdge(lastClickedVertex, v);
                            lastClickedVertex.selected = false;
                            lastClickedVertex = null;

                            if(weighted)
                            {
                                inputEdge = newEdge;
                                newEdge.SetProperty(Property.EdgeWeightId, "");
                                inputWeight = newEdge.GetProperty(Property.EdgeWeightId);
                                //Console.WriteLine("Enter edge weight");
                                edgeInputLabel.visible = true;
                            }
                        }
                        else
                        {
                            lastClickedVertex = v;
                            lastClickedVertex.selected = true;
                        }
                    }

                }

                if (!lmbDown)
                {
                    lastMousePos = Mouse.GetPosition(window);
                    lmbDown = true;
                }

            }
            else if(e.Button == Mouse.Button.Right)
            {
                if(inputEdge!=null)
                {
                    activeGraph.RemoveEdge(inputEdge);
                    inputWeight = null;
                    inputEdge = null;
                    edgeInputLabel.visible = false;
                }
                else if(v!=null)
                {
                    if(activeVertexMenu!=null)activeVertexMenu.Remove();
                    activeVertexMenu = new UiVertexMenu(v, activeGraph, mousePos.X, mousePos.Y);
                    gui.Add(activeVertexMenu);
                }
                else if(edge!=null)
                {
                    if (activeEdgeMenu != null) activeEdgeMenu.Remove();
                    activeEdgeMenu = new UiEdgeMenu(edge, activeGraph, this, mousePos.X, mousePos.Y);
                    gui.Add(activeEdgeMenu);
                }
                else
                {
                    rmbMenu.X = mousePos.X;
                    rmbMenu.Y = mousePos.Y;
                    rmbMenu.visible = true;
                }
            }
        }
        void menu_Generate(UiComponent sender, Object arg)
        {
            Vertex.ResetCounter();
            Graph g = new Graph();
            int n = random.Next(50);
            int m = random.Next(100);
            for (int i = 0; i < n; i++)
            {
                Vertex v = new Vertex((float)random.NextDouble() * 1000 - 500.0f, (float)random.NextDouble() * 600 - 300.0f);
                g.AddVertex(v);
                if (i == 0) continue;

                int connections = random.Next(1, (int)Math.Min(i, 3));
                for(int j = 0; j < connections; j++)
                {
                    int vo = random.Next(0, i);

                    bool contains = false;
                    foreach(Edge e in v.edges)
                    {
                        if(e.source.id == vo || e.destination.id == vo)
                        {
                            contains = true;
                            break;
                        }
                    }
                    if (contains) j--;
                    else g.AddEdge(v.id, vo);
                }
            }

            

            fs.SetForce(50);

            activeGraph = g;
            fs.SetGraph(g);
        }
 public float CalculateDistance(Vertex a, Vertex b)
 {
     float dx = a.x - b.x;
     float dy = a.y - b.y;
     return (float)Math.Sqrt(dx * dx + dy * dy);
 }