com.mycompany.complexity.tool.mvn.TreeLayoutDois.java Source code

Java tutorial

Introduction

Here is the source code for com.mycompany.complexity.tool.mvn.TreeLayoutDois.java

Source

/*
 * Copyright (c) 2005, the JUNG Project and the Regents of the University of
 * California All rights reserved.
 *
 * This software is open-source under the BSD license; see either "license.txt"
 * or http://jung.sourceforge.net/license.txt for a description.
 *
 * Created on Jul 9, 2005
 */
package com.mycompany.complexity.tool.mvn;

import edu.uci.ics.jung.algorithms.layout.Layout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.map.LazyMap;

import edu.uci.ics.jung.graph.Forest;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.util.TreeUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;

/**
 * @author Karlheinz Toni
 * @author Tom Nelson - converted to jung2
 *
 */
public class TreeLayoutDois<V extends Comparable, E> implements Layout<V, E> {

    protected Dimension size = new Dimension(600, 600);
    protected Forest<V, E> graph;
    protected Map<V, Integer> basePositions = new HashMap<V, Integer>();

    protected Map<V, Point2D> locations = LazyMap.decorate(new HashMap<V, Point2D>(),
            new Transformer<V, Point2D>() {
                public Point2D transform(V arg0) {
                    return new Point2D.Double();
                }
            });
    //       LazyMap.decorate(new HashMap<V, Point2D>(),
    //             new Function<V,Point2D>() {
    //               public Point2D transform(V arg0) {
    //                  return new Point2D.Double();
    //               }});

    protected transient Set<V> alreadyDone = new HashSet<V>();

    /**
     * The default horizontal vertex spacing. Initialized to 50.
     */
    public static int DEFAULT_DISTX = 50;

    /**
     * The default vertical vertex spacing. Initialized to 50.
     */
    public static int DEFAULT_DISTY = 50;

    /**
     * The horizontal vertex spacing. Defaults to {@code DEFAULT_XDIST}.
     */
    protected int distX = 50;

    /**
     * The vertical vertex spacing. Defaults to {@code DEFAULT_YDIST}.
     */
    protected int distY = 50;

    protected transient Point m_currentPoint = new Point();

    protected Set<V> alreadyCalculatedY = new HashSet<>();
    protected int maxHeight;

    /**
     * Creates an instance for the specified graph with default X and Y
     * distances.
     */
    public TreeLayoutDois(Forest<V, E> g) {
        this(g, DEFAULT_DISTX, DEFAULT_DISTY);
    }

    /**
     * Creates an instance for the specified graph and X distance with default Y
     * distance.
     */
    public TreeLayoutDois(Forest<V, E> g, int distx) {
        this(g, distx, DEFAULT_DISTY);
    }

    /**
     * Creates an instance for the specified graph, X distance, and Y distance.
     */
    public TreeLayoutDois(Forest<V, E> g, int distx, int disty) {
        if (g == null) {
            throw new IllegalArgumentException("Graph must be non-null");
        }
        if (distx < 1 || disty < 1) {
            throw new IllegalArgumentException("X and Y distances must each be positive");
        }
        this.graph = g;
        this.distX = distx;
        this.distY = disty;
        this.maxHeight = calculateDimensionY(TreeUtils.getRoots(graph));
        buildTree();
    }

    protected void buildTree() {
        this.m_currentPoint = new Point(0, 20);
        Collection<V> roots = TreeUtils.getRoots(graph);
        if (roots.size() > 0 && graph != null) {
            calculateDimensionX(roots);
            for (V v : roots) {
                calculateDimensionX(v);
                m_currentPoint.x += this.basePositions.get(v) / 2 + this.distX;
                buildTree(v, this.m_currentPoint.x);
            }
        }
        int width = 0;
        for (V v : roots) {
            width += basePositions.get(v);
        }
    }

    protected void buildTree(V v, int x) {

        if (!alreadyDone.contains(v)) {
            alreadyDone.add(v);

            this.m_currentPoint.x = x;

            if (graph.inDegree(v) > 4) {
                this.m_currentPoint.y += maxHeight;
                this.m_currentPoint.x = size.width / 2;
            } else {
                //go one level further down
                this.m_currentPoint.y += this.distY;
            }
            this.setCurrentPositionFor(v);

            int sizeXofCurrent = basePositions.get(v);

            int lastX = x - sizeXofCurrent / 2;

            int sizeXofChild;
            int startXofChild;

            for (V element : graph.getSuccessors(v)) {
                sizeXofChild = this.basePositions.get(element);
                startXofChild = lastX + sizeXofChild / 2;
                buildTree(element, startXofChild);
                lastX = lastX + sizeXofChild + distX;
            }
            if (graph.inDegree(v) > 5) {
                this.m_currentPoint.y -= this.maxHeight;
            } else {
                this.m_currentPoint.y -= this.distY;
            }

        }
    }

    private int calculateDimensionX(V v) {

        int size = 0;
        int childrenNum = graph.getSuccessors(v).size();

        if (childrenNum != 0) {
            for (V element : graph.getSuccessors(v)) {
                size += calculateDimensionX(element) + distX;
            }
        }
        size = Math.max(0, size - distX);
        basePositions.put(v, size);

        return size;
    }

    private int calculateDimensionX(Collection<V> roots) {

        int size = 0;
        for (V v : roots) {
            int childrenNum = graph.getSuccessors(v).size();

            if (childrenNum != 0) {
                for (V element : graph.getSuccessors(v)) {
                    size += calculateDimensionX(element) + distX;
                }
            }
            size = Math.max(0, size - distX);
            basePositions.put(v, size);
        }

        return size;
    }

    private int calculateDimensionY(V v) {

        int size = 0;
        int childrenNum = graph.getSuccessors(v).size();
        List<Integer> maxSize = new ArrayList<>();

        if (childrenNum != 0) {
            for (V element : graph.getSuccessors(v)) {
                if (!alreadyCalculatedY.contains(element)) {
                    alreadyCalculatedY.add(element);
                    size += calculateDimensionY(element) + distY;
                }
            }
        }
        size = Math.max(0, size - distY);
        maxSize.add(size);

        return Collections.max(maxSize);
    }

    private int calculateDimensionY(Collection<V> roots) {

        int size = 0;
        List<Integer> maxSize = new ArrayList<>();
        for (V v : roots) {
            int childrenNum = graph.getSuccessors(v).size();

            if (childrenNum != 0) {
                for (V element : graph.getSuccessors(v)) {
                    if (!alreadyCalculatedY.contains(element)) {
                        alreadyCalculatedY.add(element);
                        size += calculateDimensionY(element) + distY;
                    }
                }
            }
            size = Math.max(0, size - distY);
            maxSize.add(size);
        }

        return Collections.max(maxSize);
    }

    /**
     * This method is not supported by this class. The size of the layout is
     * determined by the topology of the tree, and by the horizontal and
     * vertical spacing (optionally set by the constructor).
     */
    public void setSize(Dimension size) {
        throw new UnsupportedOperationException("Size of TreeLayout is set" + " by vertex spacing in constructor");
    }

    protected void setCurrentPositionFor(V vertex) {
        int x = m_currentPoint.x;
        int y = m_currentPoint.y;
        if (x < 0) {
            size.width -= x;
        }

        if (x > size.width - distX) {
            size.width = x + distX;
        }

        if (y < 0) {
            size.height -= y;
        }
        if (y > size.height - distY) {
            size.height = y + distY;
        }
        locations.get(vertex).setLocation(m_currentPoint);

    }

    public Graph<V, E> getGraph() {
        return graph;
    }

    public Dimension getSize() {
        return size;
    }

    public void initialize() {

    }

    public boolean isLocked(V v) {
        return false;
    }

    public void lock(V v, boolean state) {
    }

    public void reset() {
    }

    public void setGraph(Graph<V, E> graph) {
        if (graph instanceof Forest) {
            this.graph = (Forest<V, E>) graph;
            buildTree();
        } else {
            throw new IllegalArgumentException("graph must be a Forest");
        }
    }

    public void setInitializer(Function<V, Point2D> initializer) {
    }

    /**
     * Returns the center of this layout's area.
     */
    public Point2D getCenter() {
        return new Point2D.Double(size.getWidth() / 2, size.getHeight() / 2);
    }

    public void setLocation(V v, Point2D location) {
        locations.get(v).setLocation(location);
    }

    public Point2D transform(V v) {
        return locations.get(v);
    }

    public void setInitializer(Transformer<V, Point2D> initializer) {
    }
}