// (c): Matti Katila, Asko Soukka package org.fenfire.fenmm; import org.fenfire.swamp.ConstGraph; import org.fenfire.vocab.STRUCTLINK; import org.fenfire.util.Pair; import org.nongnu.libvob.VobScene; import java.util.Iterator; import java.util.List; import java.util.ArrayList; import java.lang.Math; public class MMGeometry { public static final String rcsid = ""; private final static int INITIAL_CAPACITY = 10; public static double getScale(int depth) { return 1-(Math.log(depth+1)/Math.E); } public static double getTextScale(int depth) { return 1-(Math.log(depth+1)/Math.E)/2; } private static ConstGraph g; private static int maxDepth; private static float filletLength; private static float filletWidth; private static float initRotation; public MMGeometry(ConstGraph g, float filletLength, float filletWidth, float initRotation, int maxDepth) { this.g = g; this.maxDepth = maxDepth; this.filletLength = filletLength; this.filletWidth = filletWidth; this.initRotation = initRotation; } private void getXY(double x0, double y0, double angle, int depth, double[] xyOut) { if (depth == 0 || xyOut.length < 2) return; double r = filletLength * getScale(depth); xyOut[0] = x0 + Math.sin(angle) * r; xyOut[1] = y0 + Math.cos(angle) * r; } private MMPlace getPlace(VobScene vs, int into, double x0, double y0, Object node, double angle, int depth) { double[] xy = {0f, 0f}; getXY(x0, y0, angle, depth, xy); double x = xy[0]; double y = xy[1]; double s = filletWidth * getScale(depth); int cs = vs.orthoBoxCS(into, new Pair("MMPlace", node), depth, (float)(x - s/2f), (float)(y - s/2f), 1, 1, (float)s, (float)s); return new MMPlace(cs, x, y); } /** * Get all links available with node. */ private List getLinkedNodes(ConstGraph g, Object node) { Iterator a = g.findN_11X_Iter(node, STRUCTLINK.linkedTo); Iterator b = g.findN_X11_Iter(STRUCTLINK.linkedTo, node); ArrayList nodes = new ArrayList(INITIAL_CAPACITY); while (a.hasNext()) nodes.add(a.next()); while (b.hasNext()) nodes.add(b.next()); return nodes; } private Object prevCenter = null; private double prevRotationAngle = 0f; private double prevStartAngle = 0f; private Object curCenter = null; private double curRotationAngle = 0f; private double curStartAngle = 0f; public MindNet buildMindNet(VobScene vs, int cs, List path) { MindNet net = new MindNet(); if (path.size() == 0) return net; Object node = path.get(path.size()-1); MMPlace pl = getPlace(vs, cs, 0,0, node, 0,0); net.put(node, pl, 0); List links = getLinkedNodes(g, node); if (links.size() < 1) net.link(node, node); // XXX probably not the right way else { curStartAngle = getStartAngle(path); curRotationAngle = 2f*Math.PI / links.size(); for (int i=2; i= 0 && curIndex >= 0) startAngle = prevStartAngle + prevRotationAngle*prevIndex -Math.PI + rotationAngle*(links.size() - curIndex); } return startAngle; } /** * Recursively go through all cs. */ private void buildDepth(VobScene vs, int into, MindNet net, Object centerNode, Object oldCenter, List links, double x, double y, double startAngle, double rotationAngle, int beginDepth, int endDepth) { // Create CS (within place) and put it into mindNet if (beginDepth < endDepth) { for (int i=0; i= endDepth) return; for (int i=0; i= 0) nextStartAngle = (startAngle+rotationAngle*i-Math.PI) + nextAngle*(float)(nextLinks.size()-index); else nextStartAngle = 0; buildDepth(vs, into, net, link, centerNode, nextLinks, pl.x, pl.x, nextStartAngle, nextAngle, beginDepth + 1, endDepth); } } }