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}