001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.ui.layout.springbox.implementations;
033
034import java.util.Random;
035
036import org.graphstream.ui.layout.LayoutRunner;
037import org.graphstream.ui.layout.springbox.BarnesHutLayout;
038import org.graphstream.ui.layout.springbox.NodeParticle;
039
040/**
041 * The GraphStream Spring-Box layout.
042 * 
043 * <p>
044 * This layout is the default GraphStream layout that handles dynamic graphs.
045 * It can constantly evolve according to the changes in the graph. And works
046 * well with the {@link LayoutRunner} class so that the computations stops
047 * when the layout is stable enougth. 
048 * </p>
049 * 
050 * <p>
051 * This algorithm is based on the Frutcherman-Reingold force layout algorithm
052 * modified on the attraction (the degree of nodes is taken into account to
053 * stabilize the layout as we are not only interested in the result, but also
054 * in the steps in between).
055 * </p>
056 */
057public class SpringBox extends BarnesHutLayout {
058        /**
059         * The optimal distance between nodes.
060         */
061        protected double k = 1f;
062
063        /**
064         * Default attraction.
065         */
066        protected double K1 = 0.06f; // 0.3 ??
067
068        /**
069         * Default repulsion.
070         */
071        protected double K2 = 0.024f; // 0.12 ??
072
073        /**
074         * New "Spring-Box" 2D Barnes-Hut simulation.
075         */
076        public SpringBox() {
077                this(false);
078        }
079
080        /**
081         * New "Spring-Box" Barnes-Hut simulation.
082         * 
083         * @param is3D
084         *            If true the simulation dimensions count is 3 else 2.
085         */
086        public SpringBox(boolean is3D) {
087                this(is3D, new Random(System.currentTimeMillis()));
088        }
089
090        /**
091         * New "Spring-Box" Barnes-Hut simulation.
092         * 
093         * @param is3D
094         *            If true the simulation dimensions count is 3 else 2.
095         * @param randomNumberGenerator
096         *            The random number generator to use.
097         */
098        public SpringBox(boolean is3D, Random randomNumberGenerator) {
099                super(is3D, randomNumberGenerator);
100                setQuality(0.1);
101        }
102
103        @Override
104        public String getLayoutAlgorithmName() {
105                return "SpringBox";
106        }
107
108        @Override
109        public void setQuality(double qualityLevel) {
110                super.setQuality(qualityLevel);
111
112                if (quality >= 1) {
113                        viewZone = -1;
114                } else if (quality <= 0) {
115                        viewZone = k;
116                } else {
117                        viewZone = k + (k * 10 * quality);
118                }
119        }
120
121        @Override
122        protected void chooseNodePosition(NodeParticle n0, NodeParticle n1) {
123                if(n0.frozen || n1.frozen)
124                        return;
125                
126                double delta = random.nextDouble(); //k * 0.1;
127                if (n0.getEdges().size() == 1 && n1.getEdges().size() > 1) {
128                        org.miv.pherd.geom.Point3 pos = n1.getPosition();
129                        n0.moveTo(pos.x + delta, pos.y + delta, pos.z + delta);
130                } else if (n1.getEdges().size() == 1 && n0.getEdges().size() > 1) {
131                        org.miv.pherd.geom.Point3 pos = n0.getPosition();
132                        n1.moveTo(pos.x + delta, pos.y + delta, pos.z + delta);
133                }
134        }
135
136        @Override
137        public NodeParticle newNodeParticle(String id) {
138                return new SpringBoxNodeParticle(this, id);
139        }
140}