Skip to content

Commit 07f64aa

Browse files
committed
test
1 parent 2f85657 commit 07f64aa

9 files changed

+632
-0
lines changed

Controller/NodeController.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System;
2+
using System.Drawing;
3+
using System.Windows.Forms;
4+
5+
namespace AutoLayoutApplication
6+
{
7+
public class NodeController
8+
{
9+
private NodeCollection nodes;
10+
private Size clientSize;
11+
12+
public NodeController(NodeCollection nodes, Size clientSize)
13+
{
14+
this.nodes = nodes;
15+
this.clientSize = clientSize;
16+
}
17+
18+
public void TimerTick(object sender, EventArgs e)
19+
{
20+
this.nodes.MoveAll();
21+
}
22+
23+
public void MouseDown(object sender, MouseEventArgs e)
24+
{
25+
this.nodes.Lock(ToNodeX(e.X), ToNodeY(e.Y));
26+
}
27+
28+
public void MouseMove(object sender, MouseEventArgs e)
29+
{
30+
this.nodes.Drag(ToNodeX(e.X), ToNodeY(e.Y));
31+
}
32+
33+
public void MouseUp(object sender, MouseEventArgs e)
34+
{
35+
this.nodes.Unlock();
36+
}
37+
38+
private double ToNodeX(int x)
39+
{
40+
return (double)(x - this.clientSize.Width / 2);
41+
}
42+
43+
private double ToNodeY(int y)
44+
{
45+
return (double)(y - this.clientSize.Height / 2);
46+
}
47+
}
48+
}

Controller/TimerController.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
3+
namespace AutoLayoutApplication
4+
{
5+
public class TimerController
6+
{
7+
private TimerSwitch timerSwitch;
8+
9+
public TimerController(TimerSwitch timerSwitch)
10+
{
11+
this.timerSwitch = timerSwitch;
12+
}
13+
14+
public void ButtonClick(object sender, EventArgs e)
15+
{
16+
this.timerSwitch.Enabled = !(this.timerSwitch.Enabled);
17+
}
18+
}
19+
}

Model/Node.cs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace AutoLayoutApplication
5+
{
6+
public class Node
7+
{
8+
public string Name { get; private set; }
9+
public ICollection<Node> Neighbors { get; private set; }
10+
11+
public Vector R { get; set; }
12+
public Vector V { get; set; }
13+
14+
public Node(string name)
15+
{
16+
this.Name = name;
17+
this.Neighbors = new List<Node>();
18+
}
19+
20+
public Vector GetSpringForce(Node n)
21+
{
22+
// ばねの力は自然長からの変位に比例 (比例定数 -k, ばねの長さ l)
23+
const double k = 0.1d;
24+
const double l = 60.0d;
25+
double dx = this.R.X - n.R.X;
26+
double dy = this.R.Y - n.R.Y;
27+
double d2 = dx * dx + dy * dy;
28+
if (d2 < double.Epsilon)
29+
{
30+
// 距離0の時は例外として乱数で決定
31+
Random rand = new Random();
32+
return new Vector()
33+
{
34+
X = rand.NextDouble() - 0.5d,
35+
Y = rand.NextDouble() - 0.5d
36+
};
37+
}
38+
double d = Math.Sqrt(d2);
39+
double cos = dx / d;
40+
double sin = dy / d;
41+
double dl = d - l;
42+
return new Vector()
43+
{
44+
X = -k * dl * cos,
45+
Y = -k * dl * sin
46+
};
47+
}
48+
49+
public Vector GetReplusiveForce(Node n)
50+
{
51+
// 反発は距離の2乗に反比例 (比例定数 g)
52+
const double g = 500.0d;
53+
double dx = this.R.X - n.R.X;
54+
double dy = this.R.Y - n.R.Y;
55+
double d2 = dx * dx + dy * dy;
56+
if (d2 < double.Epsilon)
57+
{
58+
// 距離0の時は例外として乱数で決定
59+
Random rand = new Random();
60+
return new Vector()
61+
{
62+
X = rand.NextDouble() - 0.5d,
63+
Y = rand.NextDouble() - 0.5d
64+
};
65+
}
66+
double d = Math.Sqrt(d2);
67+
double cos = dx / d;
68+
double sin = dy / d;
69+
return new Vector()
70+
{
71+
X = g / d2 * cos,
72+
Y = g / d2 * sin
73+
};
74+
}
75+
76+
public Vector GetFrictionalForce()
77+
{
78+
// 摩擦力は速度に比例 (比例定数 -m)
79+
const double m = 0.3d;
80+
return new Vector()
81+
{
82+
X = -m * this.V.X,
83+
Y = -m * this.V.Y
84+
};
85+
}
86+
87+
public void MoveEular(double dt, Vector f)
88+
{
89+
// 質量は1とする
90+
this.R = new Vector()
91+
{
92+
X = this.R.X + dt * this.V.X,
93+
Y = this.R.Y + dt * this.V.Y
94+
};
95+
this.V = new Vector()
96+
{
97+
X = this.V.X + dt * f.X,
98+
Y = this.V.Y + dt * f.Y
99+
};
100+
}
101+
}
102+
}

Model/NodeCollection.cs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using System.Collections.Generic;
2+
using System.ComponentModel;
3+
4+
namespace AutoLayoutApplication
5+
{
6+
public class NodeCollection : Dictionary<string, Node>, INotifyPropertyChanged
7+
{
8+
public event PropertyChangedEventHandler PropertyChanged;
9+
10+
private Node lockedNode;
11+
12+
public NodeCollection Add(params string[] names)
13+
{
14+
foreach (string name in names)
15+
{
16+
this[name] = new Node(name);
17+
}
18+
return this;
19+
}
20+
21+
public NodeCollection Link(params string[] links)
22+
{
23+
foreach (string link in links)
24+
{
25+
string[] n = link.Split(',');
26+
this[n[0]].Neighbors.Add(this[n[1]]);
27+
this[n[1]].Neighbors.Add(this[n[0]]);
28+
}
29+
return this;
30+
}
31+
32+
public void MoveAll()
33+
{
34+
const double dt = 0.1d;
35+
foreach (Node n in this.Values)
36+
{
37+
if (n == this.lockedNode)
38+
{
39+
continue;
40+
}
41+
Vector f = new Vector();
42+
foreach (Node nn in n.Neighbors)
43+
{
44+
f += n.GetSpringForce(nn);
45+
}
46+
foreach (Node nn in this.Values)
47+
{
48+
if (n != nn)
49+
{
50+
f += n.GetReplusiveForce(nn);
51+
}
52+
}
53+
f += n.GetFrictionalForce();
54+
n.MoveEular(dt, f);
55+
}
56+
this.OnProeprtyChanged("Item");
57+
}
58+
59+
public void Lock(double x, double y)
60+
{
61+
// 指定した座標に一番近いノードをロックする
62+
Node nearlestNode = null;
63+
double nearlestD2 = double.PositiveInfinity;
64+
foreach (Node n in this.Values)
65+
{
66+
double d2 = (n.R.X - x) * (n.R.X - x) + (n.R.Y - y) * (n.R.Y - y);
67+
if (d2 < nearlestD2)
68+
{
69+
nearlestNode = n;
70+
nearlestD2 = d2;
71+
}
72+
}
73+
this.lockedNode = nearlestNode;
74+
nearlestNode.R = new Vector
75+
{
76+
X = x,
77+
Y = y
78+
};
79+
nearlestNode.V = new Vector();
80+
}
81+
82+
public void Drag(double x, double y)
83+
{
84+
if (this.lockedNode == null)
85+
{
86+
return;
87+
}
88+
this.lockedNode.R = new Vector
89+
{
90+
X = x,
91+
Y = y
92+
};
93+
}
94+
95+
public void Unlock()
96+
{
97+
this.lockedNode = null;
98+
}
99+
100+
public bool IsLocked(Node n)
101+
{
102+
if (n == null) return false;
103+
return (n == this.lockedNode);
104+
}
105+
106+
protected void OnProeprtyChanged(string propertyName)
107+
{
108+
PropertyChangedEventHandler handler = this.PropertyChanged;
109+
if (handler != null)
110+
{
111+
handler(this, new PropertyChangedEventArgs(propertyName));
112+
}
113+
}
114+
}
115+
}

Model/TimerSwitch.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.ComponentModel;
2+
3+
namespace AutoLayoutApplication
4+
{
5+
public class TimerSwitch : INotifyPropertyChanged
6+
{
7+
public event PropertyChangedEventHandler PropertyChanged;
8+
9+
private bool _enabled;
10+
11+
public bool Enabled
12+
{
13+
get
14+
{
15+
return this._enabled;
16+
}
17+
set
18+
{
19+
if (this._enabled != value)
20+
{
21+
this._enabled = value;
22+
this.OnProeprtyChanged("Enabled");
23+
}
24+
}
25+
}
26+
27+
protected void OnProeprtyChanged(string propertyName)
28+
{
29+
PropertyChangedEventHandler handler = this.PropertyChanged;
30+
if (handler != null)
31+
{
32+
handler(this, new PropertyChangedEventArgs(propertyName));
33+
}
34+
}
35+
}
36+
}

Model/Vector.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+

2+
namespace AutoLayoutApplication
3+
{
4+
public struct Vector
5+
{
6+
public double X;
7+
public double Y;
8+
9+
public static Vector operator +(Vector v1, Vector v2)
10+
{
11+
return new Vector()
12+
{
13+
X = v1.X + v2.X,
14+
Y = v1.Y + v2.Y
15+
};
16+
}
17+
}
18+
}

0 commit comments

Comments
 (0)