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; 033 034import org.graphstream.stream.Pipe; 035import org.graphstream.ui.geom.Point3; 036 037/** 038 * Layout algorithm interface. 039 * 040 * <p> 041 * The layout algorithm role is to compute the best possible positions of nodes 042 * in a given space (2D or 3D) and eventually break points for edges if 043 * supported using either aesthetic constraints, hierarchical constraints or 044 * grouping constraints. As there are many such algorithms with distinct 045 * qualities and uses, this interface defines what is awaited from a general 046 * layout algorithm. 047 * </p> 048 * 049 * <p> 050 * This algorithm is a {@link Pipe} that receives notifications on the graph 051 * eventually maintain an internal representation of it (or for some of them 052 * work directly on the graph), and in return send graph events to give each 053 * node a position via "xyz" attributes. Some algorithms may also export more 054 * information for nodes and edges. For example some algorithms are also able to 055 * work on the shape of an edge or the shape of a node. 056 * </p> 057 * 058 * <p> 059 * The layout algorithm described by this interface may be iterative. Some 060 * algorithm will compute directly their final representation of the graph in 061 * one pass. However most algorithms will probably work step by step until a 062 * global quality function is satisfied. This is the best way to handle evolving 063 * graphs. 064 * </p> 065 * 066 * <p> 067 * This behavior has been chosen because this algorithm is often run aside the 068 * main thread that works on the graph. We want a thread to be able to compute a 069 * new layout on its side, without disturbing the main algorithm run on the 070 * graph. See the {@link org.graphstream.ui.layout.LayoutRunner} for an helper 071 * class allowing to create such a thread. 072 * </p> 073 * 074 * <p> 075 * To be notified of the layout changes dynamically, you must register as a 076 * sink of the layout. 077 * </p> 078 * 079 * <p> 080 * The graph viewers in the UI package often use a layout algorithm to present 081 * graphs on screen. 082 * </p> 083 * 084 * @since 20050706 085 */ 086public interface Layout extends Pipe { 087 /** 088 * Name of the layout algorithm. 089 */ 090 String getLayoutAlgorithmName(); 091 092 /** 093 * How many nodes moved during the last step?. When this method returns 094 * zero, the layout stabilized. 095 */ 096 int getNodeMovedCount(); 097 098 /** 099 * Estimate of how close to stabilization the layout algorithm is. 100 * 101 * @return a value between 0 and 1. 1 means fully stabilized. 102 */ 103 double getStabilization(); 104 105 /** 106 * Above which value a correct stabilization is achieved? 107 * 108 * @return The stabilization limit. 109 */ 110 double getStabilizationLimit(); 111 112 /** 113 * Smallest point in space of the layout bounding box. 114 */ 115 Point3 getLowPoint(); 116 117 /** 118 * Largest point in space of the layout bounding box. 119 */ 120 Point3 getHiPoint(); 121 122 /** 123 * Number of calls made to step() so far. 124 */ 125 int getSteps(); 126 127 /** 128 * Time in nanoseconds used by the last call to step(). 129 */ 130 long getLastStepTime(); 131 132 /** 133 * The current layout algorithm quality. A number between 0 and 1 with 1 the 134 * highest (but probably slowest) quality. 135 * 136 * @return A number between 0 and 1. 137 */ 138 double getQuality(); 139 140 /** 141 * The current layout force. 142 * 143 * @return A real number. 144 */ 145 double getForce(); 146 147 /** 148 * Clears the whole nodes and edges structures 149 */ 150 void clear(); 151 152 /** 153 * The general "speed" of the algorithm. For some algorithm this will have 154 * no effect. For most "dynamic" algorithms, this change the way iterations 155 * toward stabilization are done. 156 * 157 * @param value 158 * A number in [0..1]. 159 */ 160 void setForce(double value); 161 162 /** 163 * Change the stabilization limit for this layout algorithm. 164 * 165 * <p> 166 * The stabilization is a number between 0 and 1 that indicates how close to 167 * stabilization (no nodes need to move) the layout is. The value 1 means 168 * the layout is fully stabilized. Naturally this is often only an 169 * indication only, for some algorithms, it is difficult to determine if the 170 * layout is correct or acceptable enough. You can get the actual 171 * stabilization limit using {@link #getStabilizationLimit()}. You can get 172 * the actual stabilization using {@link #getStabilization()}. 173 * </p> 174 * 175 * <p> 176 * Be careful, most layout classes do not use the stabilization limit, this 177 * number is mostly used the process that control the layout, like the 178 * {@link LayoutRunner} for example. The stabilization limit is only an 179 * indication with a default set for each layout algorithm. However this 180 * default can be changed using this method, or by storing on the graph an 181 * attribute "layout.stabilization-limit" (or "layout.stabilisation-limit"). 182 * </p> 183 * 184 * <p> 185 * The convention is that the value 0 means that the process controlling the 186 * layout will not stop the layout (will therefore not consider the 187 * stabilization limit). In other words the layout will compute endlessly. 188 * </p> 189 * 190 * @param value 191 * The new stabilization limit, 0 means no need to stabilize. 192 * Else a value larger than zero or equal to 1 is accepted. 193 */ 194 void setStabilizationLimit(double value); 195 196 /** 197 * Set the overall quality level, a number between 0 and 1 with 1 the 198 * highest quality available, but often with a slower computation. 199 * 200 * @param qualityLevel 201 * The quality level, a number between 0 and 1. 202 */ 203 void setQuality(double qualityLevel); 204 205 /** 206 * If true, node informations messages are sent for every node. This is 207 * mainly for debugging and slows down the process a lot. The contents of 208 * the node information is specific to the algorithm, and sent via a 209 * specific "layout.info" attribute. 210 * 211 * @param send 212 * If true, send node informations to a "layout.info" attribute. 213 */ 214 void setSendNodeInfos(boolean send); 215 216 /** 217 * Add a random vector whose length is 10% of the size of the graph to all 218 * node positions. 219 */ 220 void shake(); 221 222 /** 223 * Move a node by force to a new location. It is preferable to first freeze 224 * the node before moving it by force, and then un-freeze it. 225 * 226 * @param id 227 * The node identifier. 228 * @param x 229 * The node new X. 230 * @param y 231 * The node new Y. 232 * @param z 233 * The node new Z. 234 */ 235 void moveNode(String id, double x, double y, double z); 236 237 /** 238 * Freeze or un-freeze a node. The freezed node position will not be changed 239 * by the algorithm until un-freezed. 240 * 241 * @param id 242 * The node identifier. 243 * @param frozen 244 * If true the node is frozen. 245 */ 246 void freezeNode(String id, boolean frozen); 247 248 /** 249 * Method to call repeatedly to compute the layout. 250 * 251 * <p> 252 * This method implements the layout algorithm proper. It must be called in 253 * a loop, until the layout stabilizes. You can know if the layout is stable 254 * by using the {@link #getNodeMovedCount()} method that returns the number 255 * of node that have moved during the last call to step(). 256 * </p> 257 * 258 * <p> 259 * The listener is called by this method, therefore each call to step() will 260 * also trigger layout events, allowing to reproduce the layout process 261 * graphically for example. You can insert the listener only when the layout 262 * stabilized, and then call step() anew if you do not want to observe the 263 * layout process. 264 * </p> 265 */ 266 void compute(); 267}