物理法則のターゲット
現在、すべての物理法則は「すべての頂点のリスト」と「すべての辺のリスト」への参照を持っている。しかし「特定の頂点だけ天井に張り付く」だとか「特定の頂点は中心に固定」などのニーズを考えると、これは物理法則がそれぞれ「ターゲット」を持つようにした方がよい。さもなければ、頂点クラスに次々と属性を付与していく羽目になる。現状でanchored(固定されている)というフィールドを持っているが、もし仮に「一部の頂点だけ天井に張り付く」という物理法則を入れようと思ったらtoBeOnCeil(天井に張り付くべき)という属性をVertexクラスに付与するのか?それはどう考えても美しくない。じゃぁ、Vertexクラスを継承してtoBeOnCeil属性を持ったVertexClingable(貼り付ける頂点)クラスを作るのか?これも微妙。
つまり、現状は上のようになっているが、下のようにしたほうがよいのではないかと思う。
aggregator = new Aggregator();
aggregator.addLaw(new SpringEdge());
aggregator.addLaw(new Repulsion());
aggregator.addLaw(new NoVelocityIfAnchored());
aggregator = new Aggregator();
aggregator.addLaw(new SpringEdge(med.edgeList()));
aggregator.addLaw(new Repulsion(med.vertexList()));
aggregator.addLaw(new NoVelocity(med.anchoredVertexList()));
現在のPhysicalLaw(物理法則)クラス。
class PhysicalLaw{
public void apply(Context context){
}
}
適用されるたびに対象への参照を受け取っていますね。とりあえずContextクラスとその子のContextWithEdgesを取り除いて修正し、動くことを確認したのでコミットしました。現状は
aggregator = new Aggregator();
aggregator.addLaw(new SpringEdge(edgeList));
aggregator.addLaw(new Repulsion(vertexList));
aggregator.addLaw(new NoVelocityIfAnchored(vertexList));
public class NoVelocityIfAnchored extends PhysicalLaw {
private Vector target;
public NoVelocityIfAnchored(Vector target) {
this.target = target;
}
public void apply(){
for (int i = 0; i < target.size(); i++) {
MassPoint p = (MassPoint) target.get(i);
VecWithPrior zeroVel = new VecWithPrior(0.0, 2, 0.0, 2);
if(p.anchored){
p.velocityList.add(zeroVel);
}
}
}
}
という状況なので、次はNoVelocityIfAnchoredをNoVelocityに変えて、targetとしてVelocityを0にすべき頂点を受け取るように変えましょう。今日はもう9時なので続きは明日。
明日のTODO。上に書いたの。あと、MassPointがvelocityを持っているのにVertexがpositionを持っていて変。GRINEditとは関係ないけど、ソースコードにタブとスペースが混在してるみたい。Eclipseの設定を見直そう。