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); }