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 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 farNodes, ArrayList 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(), new ArrayList(), posX, posY, forceX, forceY); }*/ }