X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.debug.graphical%2Fsrc%2Forg%2Fsimantics%2Fdebug%2Fgraphical%2Flayout%2FBarnesHut2.java;fp=bundles%2Forg.simantics.debug.graphical%2Fsrc%2Forg%2Fsimantics%2Fdebug%2Fgraphical%2Flayout%2FBarnesHut2.java;h=537655f5e656c81fd38e43e03802ec1b2e76c356;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hp=e4608852f79119d318f602077721161174b77eec;hpb=24e2b34260f219f0d1644ca7a138894980e25b14;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/BarnesHut2.java b/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/BarnesHut2.java index e4608852f..537655f5e 100644 --- a/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/BarnesHut2.java +++ b/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/BarnesHut2.java @@ -1,189 +1,189 @@ -package org.simantics.debug.graphical.layout; - -import java.util.ArrayList; -import java.util.Iterator; - -public class BarnesHut2 { - - static final double OPTIMAL_DISTANCE = 150.0; - static final double C = 0.1; - static final double K = C / OPTIMAL_DISTANCE; - static final double G = K; - static final double Q = C * OPTIMAL_DISTANCE * OPTIMAL_DISTANCE; - - public static final int OCTREE_LEAF_SIZE = 25; - - public static void applyDirectedForce(Particle a, Particle b) { - double dx = a.x - b.x; - double dy = a.y - b.y; - double l2 = dx*dx + dy*dy; - double s = Q / l2; - a.fx += s * dx; - a.fy += s * dy; - } - - public static void applyDirectedForce(Particle a, OctreeNode b) { - double dx = a.x - b.massCenterX; - double dy = a.y - b.massCenterY; - double l2 = dx*dx + dy*dy; - double s = Q * b.mass / l2; - a.fx += s * dx; - a.fy += s * dy; - } - - private static abstract class OctreeNode { - double mass; - double massCenterX; - double massCenterY; - } - - private static class OctreeInnerNode extends OctreeNode { - final OctreeNode n00; - final OctreeNode n10; - final OctreeNode n01; - final OctreeNode n11; - - public OctreeInnerNode(OctreeNode n00, OctreeNode n10, OctreeNode n01, OctreeNode n11) { - this.n00 = n00; - this.n10 = n10; - this.n01 = n01; - this.n11 = n11; - - double mass00 = n00.mass; - double mass10 = n10.mass; - double mass01 = n01.mass; - double mass11 = n11.mass; - double totalMass = mass00 + mass10 + mass01 + mass11; - - this.mass = totalMass; - this.massCenterX = - (n00.massCenterX*mass00 + n10.massCenterX*mass10 + - n01.massCenterX*mass01 + n11.massCenterX*mass11) - / totalMass; - this.massCenterY = - (n00.massCenterY*mass00 + n10.massCenterY*mass10 + - n01.massCenterY*mass01 + n11.massCenterY*mass11) - / totalMass; - } - } - - private static class OctreeLeaf extends OctreeNode { - final Particle[] ps; - - public OctreeLeaf(Particle[] ps) { - this.ps = ps; - - double massCenterX = 0.0; - double massCenterY = 0.0; - for(Particle p : ps) { - massCenterX += p.x; - massCenterY += p.y; - } - - this.mass = ps.length; - this.massCenterX = massCenterX / ps.length; - this.massCenterY = massCenterY / ps.length; - } - } - - private static OctreeNode constructOctree(double minX, double minY, double maxX, double maxY, - ArrayList ps) { - if(ps.size() < OCTREE_LEAF_SIZE) - return new OctreeLeaf(ps.toArray(new Particle[ps.size()])); - - double midX = 0.5 * (minX + maxX); - double midY = 0.5 * (minY + maxY); - - ArrayList ps00 = new ArrayList(); - ArrayList ps10 = new ArrayList(); - ArrayList ps01 = new ArrayList(); - ArrayList ps11 = new ArrayList(); - - for(Particle p : ps) { - double x = p.x; - double y = p.y; - if(x < midX) { - if(y < midY) - ps00.add(p); - else - ps01.add(p); - } - else { - if(y < midY) - ps10.add(p); - else - ps11.add(p); - } - } - - return new OctreeInnerNode( - constructOctree(minX, minY, midX, midY, ps00), - constructOctree(midX, minY, maxX, midY, ps10), - constructOctree(minX, midY, midX, maxY, ps01), - constructOctree(midX, midY, maxX, maxY, ps11) - ); - } - - 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(ArrayList ps) { - Iterator it = ps.iterator(); - - Particle pFirst = it.next(); - - double minX = pFirst.x; - double minY = pFirst.y; - double maxX = pFirst.x; - double maxY = pFirst.y; - - while(it.hasNext()) { - Particle p = it.next(); - double x = p.x; - double y = p.y; - 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 void computeForce(OctreeNode octree, - ArrayList nearNodes, ArrayList farNodes) { - // TODO Auto-generated method stub - - } - - public static void computeRepulsiveForces(ArrayList ps) { - Bounds bounds = computeOctreeBounds(ps); - OctreeNode octree = constructOctree(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, ps); - computeForce(octree, new ArrayList(), new ArrayList()); - } -} +package org.simantics.debug.graphical.layout; + +import java.util.ArrayList; +import java.util.Iterator; + +public class BarnesHut2 { + + static final double OPTIMAL_DISTANCE = 150.0; + static final double C = 0.1; + static final double K = C / OPTIMAL_DISTANCE; + static final double G = K; + static final double Q = C * OPTIMAL_DISTANCE * OPTIMAL_DISTANCE; + + public static final int OCTREE_LEAF_SIZE = 25; + + public static void applyDirectedForce(Particle a, Particle b) { + double dx = a.x - b.x; + double dy = a.y - b.y; + double l2 = dx*dx + dy*dy; + double s = Q / l2; + a.fx += s * dx; + a.fy += s * dy; + } + + public static void applyDirectedForce(Particle a, OctreeNode b) { + double dx = a.x - b.massCenterX; + double dy = a.y - b.massCenterY; + double l2 = dx*dx + dy*dy; + double s = Q * b.mass / l2; + a.fx += s * dx; + a.fy += s * dy; + } + + private static abstract class OctreeNode { + double mass; + double massCenterX; + double massCenterY; + } + + private static class OctreeInnerNode extends OctreeNode { + final OctreeNode n00; + final OctreeNode n10; + final OctreeNode n01; + final OctreeNode n11; + + public OctreeInnerNode(OctreeNode n00, OctreeNode n10, OctreeNode n01, OctreeNode n11) { + this.n00 = n00; + this.n10 = n10; + this.n01 = n01; + this.n11 = n11; + + double mass00 = n00.mass; + double mass10 = n10.mass; + double mass01 = n01.mass; + double mass11 = n11.mass; + double totalMass = mass00 + mass10 + mass01 + mass11; + + this.mass = totalMass; + this.massCenterX = + (n00.massCenterX*mass00 + n10.massCenterX*mass10 + + n01.massCenterX*mass01 + n11.massCenterX*mass11) + / totalMass; + this.massCenterY = + (n00.massCenterY*mass00 + n10.massCenterY*mass10 + + n01.massCenterY*mass01 + n11.massCenterY*mass11) + / totalMass; + } + } + + private static class OctreeLeaf extends OctreeNode { + final Particle[] ps; + + public OctreeLeaf(Particle[] ps) { + this.ps = ps; + + double massCenterX = 0.0; + double massCenterY = 0.0; + for(Particle p : ps) { + massCenterX += p.x; + massCenterY += p.y; + } + + this.mass = ps.length; + this.massCenterX = massCenterX / ps.length; + this.massCenterY = massCenterY / ps.length; + } + } + + private static OctreeNode constructOctree(double minX, double minY, double maxX, double maxY, + ArrayList ps) { + if(ps.size() < OCTREE_LEAF_SIZE) + return new OctreeLeaf(ps.toArray(new Particle[ps.size()])); + + double midX = 0.5 * (minX + maxX); + double midY = 0.5 * (minY + maxY); + + ArrayList ps00 = new ArrayList(); + ArrayList ps10 = new ArrayList(); + ArrayList ps01 = new ArrayList(); + ArrayList ps11 = new ArrayList(); + + for(Particle p : ps) { + double x = p.x; + double y = p.y; + if(x < midX) { + if(y < midY) + ps00.add(p); + else + ps01.add(p); + } + else { + if(y < midY) + ps10.add(p); + else + ps11.add(p); + } + } + + return new OctreeInnerNode( + constructOctree(minX, minY, midX, midY, ps00), + constructOctree(midX, minY, maxX, midY, ps10), + constructOctree(minX, midY, midX, maxY, ps01), + constructOctree(midX, midY, maxX, maxY, ps11) + ); + } + + 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(ArrayList ps) { + Iterator it = ps.iterator(); + + Particle pFirst = it.next(); + + double minX = pFirst.x; + double minY = pFirst.y; + double maxX = pFirst.x; + double maxY = pFirst.y; + + while(it.hasNext()) { + Particle p = it.next(); + double x = p.x; + double y = p.y; + 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 void computeForce(OctreeNode octree, + ArrayList nearNodes, ArrayList farNodes) { + // TODO Auto-generated method stub + + } + + public static void computeRepulsiveForces(ArrayList ps) { + Bounds bounds = computeOctreeBounds(ps); + OctreeNode octree = constructOctree(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, ps); + computeForce(octree, new ArrayList(), new ArrayList()); + } +}