protected void attraction(Vector3 delta) { for (EdgeSpring edge : neighbours) { if (!edge.ignored) { NodeParticle other = edge.getOpposite(this); delta.set(other.pos.x - pos.x, other.pos.y - pos.y, box.is3D ? other.pos.z - pos.z : 0); double len = delta.normalize(); double k = box.k * edge.weight; double factor = box.K1 * (len - k); // delta.scalarMult( factor ); delta.scalarMult(factor * (1f / (neighbours.size() * 0.1f))); // XXX // NEW // inertia // based // on // the // node // degree. disp.add(delta); attE += factor; box.energies.accumulateEnergy(factor); } } }
/** * Compute the repulsion for each other node. This is the most precise way, but the algorithm is a * time hog : complexity is O(n^2). * * @param delta The computed displacement vector. */ protected void repulsionN2(Vector3 delta) { Iterator<Object> i = box.nodes.getParticleIdIterator(); while (i.hasNext()) { NodeParticle node = (NodeParticle) box.nodes.getParticle(i.next()); if (node != this) { delta.set(node.pos.x - pos.x, node.pos.y - pos.y, box.is3D ? node.pos.z - pos.z : 0); double len = delta.normalize(); double factor = len != 0 ? ((box.K2 / (len * len)) * node.weight) : 0.00001f; delta.scalarMult(-factor); disp.add(delta); box.energies.accumulateEnergy(factor); // TODO check this } } }
@Override public void move(int time) { if (!frozen) { disp.fill(0); Vector3 delta = new Vector3(); repE = 0; attE = 0; if (box.viewZone < 0) repulsionN2(delta); else repulsionNLogN(delta); attraction(delta); // int N = neighbours.size(); // if( N > 40 ) // System.err.printf( "* BIG ** [%05d] rep=%05.5f att=%05.5f%n", N, // repE, attE ); // else System.err.printf( // " Small [%05d] rep=%05.5f att=%05.5f%n", N, repE, attE ); disp.scalarMult(box.force); len = disp.length(); if (len > (box.area / 2)) { disp.scalarMult((box.area / 2) / len); len = box.area / 2; } box.avgLength += len; if (len > box.maxMoveLength) box.maxMoveLength = len; } }
protected void recurseRepulsion(Cell cell, Vector3 delta) { if (intersection(cell)) { if (cell.isLeaf()) { Iterator<? extends Particle> i = cell.getParticles(); while (i.hasNext()) { NodeParticle node = (NodeParticle) i.next(); if (node != this) { delta.set(node.pos.x - pos.x, node.pos.y - pos.y, box.is3D ? node.pos.z - pos.z : 0); double len = delta.normalize(); if (len > 0) // && len < ( box.k * box.viewZone ) ) { if (len < box.k) len = box.k; // XXX NEW To prevent infinite // repulsion. double factor = len != 0 ? ((box.K2 / (len * len)) * node.weight) : 0.00001; box.energies.accumulateEnergy(factor); // TODO check // this repE += factor; delta.scalarMult(-factor); disp.add(delta); } } } } else { int div = cell.getSpace().getDivisions(); for (int i = 0; i < div; i++) recurseRepulsion(cell.getSub(i), delta); } } else { if (cell != this.cell) { BarycenterCellData bary = (BarycenterCellData) cell.getData(); double dist = bary.distanceFrom(pos); double size = cell.getSpace().getSize(); if ((!cell.isLeaf()) && ((size / dist) > box.theta)) { int div = cell.getSpace().getDivisions(); for (int i = 0; i < div; i++) recurseRepulsion(cell.getSub(i), delta); } else { if (bary.weight != 0) { // System.err.printf( // "applying bary %s [depth=%d weight=%d]%n", // cell.getId(), cell.getDepth(), (int)bary.weight ); delta.set( bary.center.x - pos.x, bary.center.y - pos.y, box.is3D ? bary.center.z - pos.z : 0); double len = delta.normalize(); if (len > 0) { if (len < box.k) len = box.k; // XXX NEW To prevent infinite // repulsion. double factor = len != 0 ? ((box.K2 / (len * len)) * (bary.weight)) : 0.00001f; box.energies.accumulateEnergy(factor); delta.scalarMult(-factor); repE += factor; disp.add(delta); } } } } } }