-package org.simantics.debug.graphical.layout;
-
-public class BarnesHut {
-
- static class Bounds {
- final double minX;
- final double minY;
- final double maxX;
- final double maxY;
-
- public Bounds(double minX, double minY, double maxX, double maxY) {
- this.minX = minX;
- this.minY = minY;
- this.maxX = maxX;
- this.maxY = maxY;
- }
- }
-
- private static Bounds computeOctreeBounds(double[] posX, double[] posY) {
- double minX = posX[0];
- double minY = posY[0];
- double maxX = posX[0];
- double maxY = posY[0];
-
- for(int i=1;i<posX.length;++i) {
- double x = posX[i];
- double y = posY[i];
- if(x < minX)
- minX = x;
- else if(x > maxX)
- maxX = x;
- if(y < minY)
- minY = y;
- else if(y > maxY)
- maxY = y;
- }
-
- double diff = (maxX - minX) - (maxY - minY);
- diff *= 0.5;
- if(diff > 0.0) {
- minY -= diff;
- maxY += diff;
- }
- else {
- minX += diff;
- maxX -= diff;
- }
- return new Bounds(minX, minY, maxX, maxY);
- }
-
- private static class VecRef {
- double x;
- double y;
- }
-
- /*private static void force(VecRef f, double x1, double y1, double x2, double y2) {
- double dx = x2 - x1;
- double dy = y2 - y1;
- double l2 = dx*dx + dy*dy;
- double s = Q / l2;
- f.x -= s * dx;
- f.y -= s * dy;
- }
-
- private static void forceNear(VecRef f, double x1, double y1, OctreeNode node, double[] posX, double[] posY) {
- if(node instanceof OctreeLeaf) {
- for(int id : ((OctreeLeaf)node).ids) {
- force(f, x1, y1, posX[id], posY[id]);
- }
- }
- else {
- OctreeInnerNode inner = (OctreeInnerNode)node;
- forceNear(f, x1, y1, inner.n00, posX, posY);
- forceNear(f, x1, y1, inner.n10, posX, posY);
- forceNear(f, x1, y1, inner.n01, posX, posY);
- forceNear(f, x1, y1, inner.n11, posX, posY);
- }
- }
-
- private static void forceFar(VecRef f, double x1, double y1, OctreeNode node) {
- double dx = node.massCenterX - x1;
- double dy = node.massCenterY - y1;
- double l2 = dx*dx + dy*dy;
- double s = Q * node.mass / l2;
- f.x -= s * dx;
- f.y -= s * dy;
- }
-
- private static void computeForce(OctreeNode octree,
- ArrayList<OctreeNode> farNodes,
- ArrayList<OctreeNode> nearNodes,
- double[] posX, double[] posY,
- double[] forceX, double[] forceY) {
- VecRef f = new VecRef();
- if(octree instanceof OctreeLeaf) {
- int[] ids = ((OctreeLeaf)octree).ids;
- for(int i=0;i<ids.length;++i) {
- int id = ids[i];
-
- double x = posX[id];
- double y = posY[id];
- f.x = 0.0;
- f.y = 0.0;
-
- for(int j=0;j<ids.length;++j)
- if(j != i) {
- int id2 = ids[j];
- force(f, x, y, posX[id2], posY[id2]);
- }
- for(OctreeNode node : nearNodes)
- forceNear(f, x, y, node, posX, posY);
- for(OctreeNode node : farNodes)
- forceFar(f, x, y, node);
-
- forceX[id] += f.x;
- forceY[id] += f.y;
- }
- }
- else {
- OctreeInnerNode inner = (OctreeInnerNode)octree;
- computeForce(inner.n00, farNodes, nearNodes, posX, posY, forceX, forceY);
- computeForce(inner.n10, farNodes, nearNodes, posX, posY, forceX, forceY);
- computeForce(inner.n01, farNodes, nearNodes, posX, posY, forceX, forceY);
- computeForce(inner.n11, farNodes, nearNodes, posX, posY, forceX, forceY);
- }
- }
-
- public static void computeRepulsiveForces(double[] posX, double[] posY, double[] forceX, double[] forceY) {
- Bounds bounds = computeOctreeBounds(posX, posY);
-
- TIntArrayList ids = new TIntArrayList(posX.length);
- for(int i=0;i<posX.length;++i)
- ids.add(i);
- OctreeNode octree = constructOctree(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, ids, posX, posY);
-
- computeForce(octree, new ArrayList<OctreeNode>(), new ArrayList<OctreeNode>(), posX, posY, forceX, forceY);
- }*/
-
-}