基本信息
源码名称:A 2D/3D force directed graph algorithm in C#
源码大小:0.07M
文件格式:.zip
开发语言:C#
更新时间:2020-02-20
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
namespace EpForceDirectedGraphDemo
{
public partial class ForceDirectedGraphForm : Form
{
const int width = 64;
const int height = 32;
Stopwatch stopwatch = new Stopwatch();
Graphics paper;
int panelTop;
int panelBottom;
int panelLeft;
int panelRight;
Dictionary<Node,GridBox> m_fdgBoxes;
Dictionary<Edge, GridLine> m_fdgLines;
Graph m_fdgGraph;
ForceDirected2D m_fdgPhysics;
Renderer m_fdgRenderer;
System.Timers.Timer timer = new System.Timers.Timer(30);
public ForceDirectedGraphForm()
{
InitializeComponent();
this.DoubleBuffered = true;
this.Width = (width 1) * 20;
this.Height = (height 1) * 20 100;
this.MaximumSize = new Size(this.Width, this.Height);
this.MaximizeBox = false;
tbStiffness.Text = "81.76";
tbRepulsion.Text = "40000.0";
tbDamping.Text = "0.5";
panelTop = 0;
panelBottom = pDrawPanel.Size.Height;
panelLeft = 0;
panelRight = pDrawPanel.Size.Width;
m_fdgBoxes = new Dictionary<Node, GridBox>();
m_fdgLines = new Dictionary<Edge, GridLine>();
m_fdgGraph = new Graph();
m_fdgPhysics = new ForceDirected2D(m_fdgGraph,81.76f,40000.0f, 0.5f);
m_fdgRenderer = new Renderer(this, m_fdgPhysics);
pDrawPanel.Paint = new PaintEventHandler(DrawPanel_Paint);
timer.Interval = 30;
timer.Elapsed = new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
pDrawPanel.Invalidate();
}
private void DrawPanel_Paint(object sender, PaintEventArgs e)
{
stopwatch.Stop();
var p = sender as Panel;
paper = e.Graphics;
GridBox box = new GridBox((panelRight - panelLeft) / 2, (panelBottom - panelTop) / 2, BoxType.Pinned);
box.DrawBox(paper);
m_fdgRenderer.Draw(0.05f); // TODO: Check Time
stopwatch.Reset();
stopwatch.Start();
}
private void ForceDirectedGraph_Paint(object sender, PaintEventArgs e)
{
}
public Pair<int, int> GraphToScreen(FDGVector2 iPos)
{
Pair<int, int> retPair = new Pair<int, int>();
retPair.first = (int)(iPos.x (((float)(panelRight - panelLeft)) / 2.0f));
retPair.second = (int)(iPos.y (((float)(panelBottom - panelTop)) / 2.0f));
return retPair;
}
public FDGVector2 ScreenToGraph(Pair<int, int> iScreenPos)
{
FDGVector2 retVec = new FDGVector2();
retVec.x= ((float)iScreenPos.first)-(((float)(panelRight-panelLeft))/2.0f);
retVec.y = ((float)iScreenPos.second) - (((float)(panelBottom - panelTop)) / 2.0f);
return retVec;
}
public void DrawLine(Edge iEdge, AbstractVector iPosition1, AbstractVector iPosition2)
{
Pair<int, int> pos1 = GraphToScreen(iPosition1 as FDGVector2);
Pair<int, int> pos2 = GraphToScreen(iPosition2 as FDGVector2);
m_fdgLines[iEdge].Set(pos1.first, pos1.second, pos2.first, pos2.second);
m_fdgLines[iEdge].DrawLine(paper);
}
public void DrawBox(Node iNode, AbstractVector iPosition)
{
Pair<int, int> pos = GraphToScreen(iPosition as FDGVector2);
m_fdgBoxes[iNode].Set(pos.first, pos.second);
m_fdgBoxes[iNode].DrawBox(paper);
}
private void btnChangeProperties_Click(object sender, EventArgs e)
{
float stiffNess = System.Convert.ToSingle(tbStiffness.Text);
m_fdgPhysics.Stiffness = stiffNess;
float repulsion = System.Convert.ToSingle(tbRepulsion.Text);
m_fdgPhysics.Repulsion = repulsion;
float damping = System.Convert.ToSingle(tbDamping.Text);
m_fdgPhysics.Damping = damping;
}
private bool addNode(string nodeName)
{
nodeName = nodeName.Trim();
if (m_fdgGraph.GetNode(tbNodeName.Text) != null)
{
return false;
}
Node newNode = m_fdgGraph.CreateNode(nodeName);
m_fdgBoxes[newNode] = new GridBox(0, 0, BoxType.Normal);
cbbFromNode.Items.Add(nodeName);
cbbToNode.Items.Add(nodeName);
lbNode.Items.Add(nodeName);
return true;
}
private void btnAddNode_Click(object sender, EventArgs e)
{
tbNodeName.Text=tbNodeName.Text.Trim();
if (tbNodeName.Text == "")
{
MessageBox.Show("Please type in the node name to insert!");
return;
}
if (!addNode(tbNodeName.Text))
{
MessageBox.Show("Node already exists in the graph!");
return;
}
}
private bool addEdge(string nodeName1, string nodeName2)
{
nodeName1 = nodeName1.Trim();
nodeName2 = nodeName2.Trim();
if (nodeName1 == nodeName2)
{
return false;
}
Node node1 = m_fdgGraph.GetNode(nodeName1);
Node node2 = m_fdgGraph.GetNode(nodeName2);
EdgeData data = new EdgeData();
string label = nodeName1 "-" nodeName2;
data.label = label;
data.length = 60.0f;
Edge newEdge = m_fdgGraph.CreateEdge(node1, node2, data);
m_fdgLines[newEdge] = new GridLine(0, 0, 0, 0);
lbEdge.Items.Add(label);
return true;
}
private void btnAddEdge_Click(object sender, EventArgs e)
{
string nodeName1 = cbbFromNode.Text;
string nodeName2 = cbbToNode.Text;
if (!addEdge(nodeName1, nodeName2))
{
MessageBox.Show("Edge cannot be connected to same node!");
return;
}
}
private void btnRemoveNode_Click(object sender, EventArgs e)
{
if (lbNode.SelectedIndex != -1)
{
int selectedIdx = lbNode.SelectedIndex;
string nodeName=(string)lbNode.SelectedItem;
Node removeNode=m_fdgGraph.GetNode(nodeName);
m_fdgBoxes.Remove(removeNode);
List<Edge> edgeList = m_fdgGraph.GetEdges(removeNode);
foreach(Edge edge in edgeList)
{
m_fdgLines.Remove(edge);
int edgeIndex=lbEdge.FindString(edge.Data.label);
lbEdge.Items.RemoveAt(edgeIndex);
}
m_fdgGraph.RemoveNode(removeNode);
cbbFromNode.Items.RemoveAt(lbNode.SelectedIndex);
cbbToNode.Items.RemoveAt(lbNode.SelectedIndex);
lbNode.Items.RemoveAt(lbNode.SelectedIndex);
if (selectedIdx != 0)
lbNode.SelectedIndex = selectedIdx-1;
lbNode.Focus();
}
else
{
MessageBox.Show("Please select a node to remove!");
}
}
private void btnRemoveEdge_Click(object sender, EventArgs e)
{
if (lbEdge.SelectedIndex != -1)
{
int selectedIdx = lbEdge.SelectedIndex;
string edgeName = (string)lbEdge.SelectedItem;
Edge removeEdge= m_fdgGraph.GetEdge(edgeName);
m_fdgLines.Remove(removeEdge);
m_fdgGraph.RemoveEdge(removeEdge);
lbEdge.Items.RemoveAt(lbEdge.SelectedIndex);
if (selectedIdx != 0)
{
lbEdge.SelectedIndex = selectedIdx - 1;
}
lbEdge.Focus();
}
else
{
MessageBox.Show("Please select an edge to remove!");
}
}
Node clickedNode;
GridBox clickedGrid;
private void pDrawPanel_MouseDown(object sender, MouseEventArgs e)
{
foreach (KeyValuePair<Node, GridBox> keyPair in m_fdgBoxes)
{
if(keyPair.Value.boxRec.IntersectsWith(new Rectangle(e.Location,new Size(1,1))))
{
clickedNode = keyPair.Key;
clickedGrid = keyPair.Value;
clickedGrid.boxType = BoxType.Pinned;
}
}
}
private void pDrawPanel_MouseMove(object sender, MouseEventArgs e)
{
if (clickedNode != null)
{
FDGVector2 vec = ScreenToGraph(new Pair<int, int>(e.Location.X, e.Location.Y));
clickedNode.Pinned = true;
m_fdgPhysics.GetPoint(clickedNode).position = vec;
}
else
{
foreach (KeyValuePair<Node, GridBox> keyPair in m_fdgBoxes)
{
if(keyPair.Value.boxRec.IntersectsWith(new Rectangle(e.Location,new Size(1,1))))
{
keyPair.Value.boxType = BoxType.Pinned;
}
else
{
keyPair.Value.boxType = BoxType.Normal;
}
}
}
}
private void pDrawPanel_MouseUp(object sender, MouseEventArgs e)
{
if (clickedNode != null)
{
clickedGrid.boxType = BoxType.Normal;
clickedNode.Pinned = false;
clickedNode = null;
clickedGrid = null;
}
}
private void tbNodeName_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
btnAddNode_Click(sender, e);
tbNodeName.Focus();
}
}
private void tbStiffness_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
btnChangeProperties_Click(sender, e);
tbStiffness.Focus();
}
}
private void tbRepulsion_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
btnChangeProperties_Click(sender, e);
tbRepulsion.Focus();
}
}
private void tbDamping_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
btnChangeProperties_Click(sender, e);
tbDamping.Focus();
}
}
private void btnLoad_Click(object sender, EventArgs e)
{
OpenFileDialog fileDialog = new OpenFileDialog();
DialogResult result = fileDialog.ShowDialog(); // Show the dialog.
if (result == DialogResult.OK) // Test result.
{
string file = fileDialog.FileName;
try
{
string text = File.ReadAllText(file);
Int32 size = text.Length;
StringReader mapXML = new StringReader(text);
XmlTextReader xmlReader = new XmlTextReader(mapXML);
while (xmlReader.Read())
{
switch (xmlReader.NodeType)
{
case XmlNodeType.Element: // The node is an Element.
if (xmlReader.Name == "Node")
{
loadNode(xmlReader);
}
else if (xmlReader.Name == "Edge")
{
loadEdge(xmlReader);
}
break;
case XmlNodeType.Text: //Display the text in each element.
break;
case XmlNodeType.EndElement: //Display end of element.
break;
}
}
}
catch (IOException)
{
}
}
}
private void loadNode(XmlTextReader iXmlReader)
{
while (iXmlReader.MoveToNextAttribute()) // Read attributes.
{
if (iXmlReader.Name == "nodeName")
addNode(iXmlReader.Value);
}
}
private void loadEdge(XmlTextReader iXmlReader)
{
string nodeName1 = null;
string nodeName2 = null;
while (iXmlReader.MoveToNextAttribute()) // Read attributes.
{
if (iXmlReader.Name == "nodeName1")
nodeName1=iXmlReader.Value;
if (iXmlReader.Name == "nodeName2")
nodeName2 = iXmlReader.Value;
}
addEdge(nodeName1, nodeName2);
}
private void btnClear_Click(object sender, EventArgs e)
{
m_fdgPhysics.Clear();
m_fdgGraph.Clear();
m_fdgBoxes.Clear();
m_fdgLines.Clear();
lbEdge.Items.Clear();
lbNode.Items.Clear();
cbbFromNode.Items.Clear();
cbbToNode.Items.Clear();
}
}
}