Prefuse: Difference between revisions
Quotation formatted →Summary |
mNo edit summary |
||
Line 2: | Line 2: | ||
'''Author''': Jeffrey Heer / UC Berkeley<br /> | '''Author''': Jeffrey Heer / UC Berkeley<br /> | ||
''' Project Webpage''': http://prefuse.sourceforge.net<br /> | '''Project Webpage''': http://prefuse.sourceforge.net<br /> | ||
''' Current Version''': | '''Current Version''': beta, June 15, 2006<br /> | ||
'''Requirements''': Java 1.4<br /> | '''Requirements''': Java 1.4<br /> | ||
'''Overview:''' using Java2D graphics library; pipeline architecture; animation and rendering support<br /><br /> | '''Overview:''' using Java2D graphics library; pipeline architecture; animation and rendering support<br /><br /> | ||
'''Base data structures''': Table, Graph, Tree<br /> | |||
'''Included visualization techniques:''' [http://www.cs.umd.edu/hcil/fisheyemenu/ Fisheye Menu], [http://prefuse.sourceforge.net/demos-radial.html Radial Graph], [http://www.cs.umd.edu/hcil/treemap/ Treemap], [http://prefuse.sourceforge.net/demos-distortion.html F+C Distortion]<br /> | |||
'''Supported File Formats''': XGMML (XML), TreeML (XML), tab-delimited text, HDir<br /><br /> | |||
'''prefuse''' is an interactive graphical open source toolkit written in Java. It is thought to support the development of sophisticated, highly interactive, and flexible [[Information Visualization]]s. The architecture of '''prefuse''' considers the [[Visualization Pipeline]], a recommendation on how to implement a visualization. To provide flexibility, a [[polylithic design]] was chosen which enables developers to implement only needed functionality and customize these to meet the own requirements. But, in contrast to a [[monolithic design]], this design needs more time to conceive and influences the architecture of the own application heavily (which is not a disadvantage as '''prefuse''' is very elaborate). | |||
Typically, '''prefuse''' is designed to visualize information which is interrelated so it can be stored in a graph or tree structure, but, also not related data can be used which is stored within a data-table. Even though the structure is hierarchical, the resulting relations must not be considered in the proper graphical representation as layout algorithms are not restricted in any way. The painting of visual items is done by using a renderer which has access to the respective item itself and the Graphics2D context of the view. This approach enables to use the whole range of available painting methods of Java, therefore, the visual representation is completely independent of the toolkit itself. | |||
Besides providing a large set of predefined elements to visualize data, most attention was set toward usability of the visualization. This is obtained by applying several interaction techniques like tooltips or dragging visual elements. But also more sophisticated techniques like [[zoom]]ing, [[pan]]ning, or [[semantic zoom]]ing are supported or partially even provided by the toolkit itself. Further, '''prefuse''' clearly distinguishes between absolute and view coordinates. This separation helps users to place all visual elements in a logical way without consideration of later applied visualization techniques that changes the entire view. | |||
''' | |||
=== Pros === | === Pros === | ||
* | * flexible | ||
* versatile pipeline | * versatile pipeline approach | ||
* clear and well thought architecture | |||
* many layout and distortion algorithms included | * many layout and distortion algorithms included | ||
* algorithms for force-based physics simulation included | * algorithms for force-based physics simulation included | ||
* custom animations (smooth transitions) | * custom animations (smooth transitions) | ||
* color maps | * color maps | ||
* | * query language to navigate within abstract data | ||
* demos and examples included | * demos and examples included | ||
* open source | * bounding management | ||
* open source | |||
* documentation of code and general guidance available | |||
* active developer community | |||
=== Cons === | === Cons === | ||
* | * [[polylithic design]] takes up more time to conceive and see first results | ||
* | * special requirements of a visualization enforce a lot of adapting work | ||
= | =General Approach= | ||
Going along with the step-wise recommendation of the [[Visualization Pipeline]], a '''prefuse''' application consists of different states of data: | |||
'''prefuse''' uses a centralized object called ''Visualization'' (former ''ItemRegistry'') which maintains and manages the whole visualization. This object has to fulfil several tasks. It stores the abstract data as well as visual analogous of these in two different tables. All transformation routines like filtering or rendering are maintained and executed by the ''Visualization'' too. Further, it maintains at least one ''Display'', a graphical component which can represent visual data of '''prefuse'''. | |||
Transformation routines are defined as ''Actions'' which are combined in ''ActionLists''. An ''ActionList'' is an executable container which is started of the ''Visualization'' whenever necessary. Once it is started, all defined ''Actions'' are executed in the given sequence. Typically, the last called ''Action'' is the ''RepaintAction'' which forces all defined ''Displays'' to perform a repaint. | |||
A ''Display'' is the view of '''prefuse'''. It can be embedded in each Java Swing application. The main task of a ''Display'' is the painting of visual structures which are defined in the respective ''Visualization''. Whenever the ''Display'' performs a repaint it requests all visual items and checks all bounds of them (bounding management). If an item is within the own area the respective rendering mechanism is called. | |||
Another important task of the ''Display'' is the providing of navigation techniques like [[zoom]]ing or [[pan]]ning. The entire view is managed by an own view coordinate system which is described with an affine transformation matrix. The most important functionality to work with this coordinate system is already predefined. | |||
Furthermore, a ''Display'' also maintains a set of ''ControlListener'' which are used to process user interactions (mouse or keyboard events). Whenever such an event occurs the respective listener is called. This listener already differs on where the event happened (e.g., blank area or a certain item). Further, a ''ControlListener'' may also start an ''ActionList'' again. | |||
== | ==Raw Data== | ||
Raw data is the base of the application. Typically, the source of raw data is a file, but also other sources like a database are thinkable. However, '''prefuse''' provides several file readers for different formats (CSV, Tab-Delimitated, etc.) that can be transformed into a data table. Further, some readers also support the reading of SQL-Database. If another source is needed, a reader can be written manually. | |||
== External links | Once the raw data is read, it is transformed into abstract data and stored within a data table. | ||
*[http://prefuse. | |||
==Abstract Data== | |||
The data table which is used to store abstract data works with data types and a definition schema which maps relations between data type and table. That means, each row contains a data record, and each column contains data values for a named data field with a specific data type. Each record of the table is referred as a ''Tuple''. | |||
Furthermore, instead of the table itself, a graph or tree may be used to store interrelated data. Instead of ''Tuples'', records are referred as ''Nodes'' which are connected to others with ''Edges''. Additionally, a tree has one defined root ''Node''. | |||
Abstract data does not contain any visual information like assignment attributes or color settings. Instead, visual attributes are extracted out of the abstract data following a defined logic. | |||
==Visual Structures== | |||
Visual structures are created when filtering the data container which contains abstract data. In case of a visualization that displays all items from the beginning on, the filtering routine must only executed once at initializing time. If the visual content changes dynamically, the filtering is executed on certain user interactions by calling a defined filtering ''ActionList''. | |||
A visual structure is referred as ''VisualItem'' which may distinguished as ''VisualNode'', ''VisualEdge'', or an aggregated item which consists of several other items. However, as a ''VisualItem'' is extended of the respective abstract entity it has full access to all abstract information too. | |||
The filtering routine which transforms the abstract data to visual analogues typically consists of following ''Actions'': | |||
* '''Filter''': This ''Action'' is responsible to transform the abstract data of the backing table to visual analogues. If no special conditions are defined, the filter creates for each ''Tuple'' a visual instance and stores them in a second table. Additionally, a filter also performs a garbage collection and may set visibility attributes of the created items. | |||
* '''Layout''': A layout takes care about placing the ''VisualItems''. Several common algorithms for graphs or trees are already predefined (e.g., ''ForceDirectedLayout'' or ''RadialTreeLayout''). | |||
* '''Assignment''': Besides layouting, also other assignments may be performed during the filtering process. Such assignments directly changes visual attributes of ''VisualItems'' like color, sizes, fonts, etc. | |||
A visual structure may also contain a paint routine, but, as all painting jobs are initialized or performed by separated renderers, these issues may also be executed by the renderer itself or any other object. | |||
==View== | |||
Typically, the rendered visual structure is not stored, instead, they are re-rendered whenever needed. However, in case of very complex but constant visual representations it makes sense to hold items in an offscreen image. | |||
Each ''VisualItem'' has got one or more associated ''Renderers'' which are maintained by a factory of the ''Visualization''. A ''Render'' has to perform two tasks: | |||
* Providing a bounding box of the item. This box is used to determine if the item must actually be painted or if it would not be visible anyway. | |||
* Providing the painting routine of the item. Paintings may be executed by the ''Renderer'' itself or delegated to other objects which are accessible of the ''Renderer''. The painting routines are not restricted in any way, but they representation should not exceed the bounding box of the item. | |||
Rendering is always performed on a repaint of the ''Display''. A repaint can be requested by the ''Visualization'', on user interaction, and on events like resizing the component, getting the focus, or changing the coordinate system of the view. However, as repaints may occur very often, developers have to ascertain that rendering jobs can are performed fast, otherwise, the performance of the whole visualization would suffer. | |||
=Details= | |||
==Package Structure== | |||
Following picture shows the most important packages of '''prefuse''' regarding to the [[Visualization Pipeline]]: | |||
These packages also contain predefined components. A default nodes and edges provide standard functionality of abstract data, standard functionality is also available in visual analogous of them. A default filter transforms all defined abstract entities to visual ones. Further, also some special functionality for common requirements are provided by own components. | |||
* '''Renderers''': ''EdgeRenderer'' to render edges between graph or tree nodes, a ''LableRenderer'' to render test items, and a ''PolygoneRenderer'' to render geometrical items. | |||
* '''Layouts''': ''RandomLayout'', ''GridLayout'', and some more to place non related data, ''ForceDirectedLayout'', ''TreeLayout'', ''RadialTreeLayout'' and others to render trees and graphs. | |||
* '''Controls''': ''DragControl'', ''ZoomControl'', ''PanControl'', ''ToolTipControl'' and several others to react on user interactions. | |||
In simple visualizations the predefined functionality will meet most requirements. If special requirements are needed the default functionality supports a step-wise developing as results can be communicated by these components until the own functionality is implemented. | |||
==Coordinates in prefuse== | |||
'''prefuse''' works with two different coordinate systems. Absolute coordinates are device-independent logical coordinates. All visual attributes like positions or sizes are defined in absolute coordinates. In contrast, view coordinates are device-depended (screen). Transformations between absolute and view coordinates are done automatically by Java painting routines. View coordinates are influenced by the system and device driver (e.g., the absolute point (0,0) is the topmost left point of the actual graphical component which may be on any position at the screen). Further, view coordinates may also be manipulated manually by using an affine transformation matrix which applies linear transformations on absolute coordinates before device-dependent routines convert them to screen coordinates. | |||
A '''prefuse''' ''Display'' provides the most important manipulating methods of this matrix. [[Zoom]]ing, [[pan]]ning, and rotation of the whole view are only done by changing the view coordinates. So, as absolute coordinates are never concerned of such transformations and translations, a user must never consider the actual view in layout, assignment, or painting routines. | |||
There are several different ways on how to apply such transformations, additionally, the ''Display'' also supports animated transformations. | |||
==User Interactions== | |||
Mouse or keyboard events are treated by using ''ControlListener''. Whenever an event occurs which is handled by a ''ControlListener'', the ''Display'' delegates the event to the respective routine. A ''ControlListener'' differs automatically which visual element is concerned of the event (the view itself or a ''VisualItem'' on the view). | |||
A ''ControlListener'' may just perform simple task like changing the mouse cursor or editing the label of an item. But, in more sophisticated applications, also task like loading new data or dragging items on the view may also be handled. Therefore, a ''ControlListener'' may also work with ''ActionLists'' to execute such tasks. Further, a ''ControlListener'' has also access to the ''Display'' to call methods like zooming or panning. Typically, each ''ControlListener'' forces a repaint when its job is done. | |||
Most of standard functionality is already predefined in ''prefuse'' and the wanted listeners just have to be set to the ''Display''. However, the ''Display'' can handle a countless of different listener. Hence, typically only a few listeners must be defined manually as they can be mixed with default ones. | |||
=Conclusion= | |||
'''prefuse''' is a very powerful toolkit, providing a large set of components and methods a developer needs to build an [[Information Visualization]]. The [[polylithic design]] is not that easy to understand in the beginning of a development, but once conceived, a visualization is easy to realize even if really special demands have to be fulfilled. Furthermore, using Prefuse forces a clear and well designed architecture of own applications. | |||
'''prefuse''' was created with most attention paid to developers who will finally work with the toolkit. In an evaluation study this goal was approved too. In the meanwhile, there is also a not so small community using and upgrading the toolkit, which is an argue for its usability. | |||
= External links = | |||
*[http://prefuse.org prefuse Homepage] | |||
*[http://vw.indiana.edu/ivsi2004/jherr/index.html prefuse Position Paper] | *[http://vw.indiana.edu/ivsi2004/jherr/index.html prefuse Position Paper] | ||
*[http://sourceforge.net/forum/forum.php?forum_id=343013 prefuse Help Forum] | |||
= References = | |||
*[Heer, 2004] Jeffrey Heer. [http://jheer.org/publications/2004-Heer-prefuse-Masters.pdf prefuse: a software framework for interactive information visualization]. Masters of Science, Computer Science Division, University of California, Berkeley, 2004. | |||
*[Heer | |||
*[Heer, 2005] Jeffrey Heer, Stuart K. Card, and James A. Landay. [http://jheer.org/publications/2005-prefuse-CHI.pdf prefuse: a toolkit for interactive information visualization. In ''CHI 2005, Human Factors in Computing Systems''], 2005. | *[Heer, 2005] Jeffrey Heer, Stuart K. Card, and James A. Landay. [http://jheer.org/publications/2005-prefuse-CHI.pdf prefuse: a toolkit for interactive information visualization. In ''CHI 2005, Human Factors in Computing Systems''], 2005. | ||
*[Heer, 2006a] Jeffrey Heer, prefuse API documentation, Retrieved at: July 06, 2006, http://prefuse.org | |||
*[Heer, 2006b] Jeffrey Heer, prefuse manual, Retrieved at: July 06, 2006, http://prefuse.org | |||
*[Sun Microsystems, 2001] Sun Microsystems, Programmer’s Guide to the Java 2DTM API - Enhanced Graphics and Imaging for Java, Retrieved at: April 20, 2006, http://java.sun.com/j2se/1.4/pdf/j2d-book.pdf | |||
[[Category:Toolkits]] | [[Category:Toolkits]] |
Revision as of 00:59, 6 July 2006
Summary
Author: Jeffrey Heer / UC Berkeley
Project Webpage: http://prefuse.sourceforge.net
Current Version: beta, June 15, 2006
Requirements: Java 1.4
Overview: using Java2D graphics library; pipeline architecture; animation and rendering support
Base data structures: Table, Graph, Tree
Included visualization techniques: Fisheye Menu, Radial Graph, Treemap, F+C Distortion
Supported File Formats: XGMML (XML), TreeML (XML), tab-delimited text, HDir
prefuse is an interactive graphical open source toolkit written in Java. It is thought to support the development of sophisticated, highly interactive, and flexible Information Visualizations. The architecture of prefuse considers the Visualization Pipeline, a recommendation on how to implement a visualization. To provide flexibility, a polylithic design was chosen which enables developers to implement only needed functionality and customize these to meet the own requirements. But, in contrast to a monolithic design, this design needs more time to conceive and influences the architecture of the own application heavily (which is not a disadvantage as prefuse is very elaborate).
Typically, prefuse is designed to visualize information which is interrelated so it can be stored in a graph or tree structure, but, also not related data can be used which is stored within a data-table. Even though the structure is hierarchical, the resulting relations must not be considered in the proper graphical representation as layout algorithms are not restricted in any way. The painting of visual items is done by using a renderer which has access to the respective item itself and the Graphics2D context of the view. This approach enables to use the whole range of available painting methods of Java, therefore, the visual representation is completely independent of the toolkit itself.
Besides providing a large set of predefined elements to visualize data, most attention was set toward usability of the visualization. This is obtained by applying several interaction techniques like tooltips or dragging visual elements. But also more sophisticated techniques like zooming, panning, or semantic zooming are supported or partially even provided by the toolkit itself. Further, prefuse clearly distinguishes between absolute and view coordinates. This separation helps users to place all visual elements in a logical way without consideration of later applied visualization techniques that changes the entire view.
Pros
- flexible
- versatile pipeline approach
- clear and well thought architecture
- many layout and distortion algorithms included
- algorithms for force-based physics simulation included
- custom animations (smooth transitions)
- color maps
- query language to navigate within abstract data
- demos and examples included
- bounding management
- open source
- documentation of code and general guidance available
- active developer community
Cons
- polylithic design takes up more time to conceive and see first results
- special requirements of a visualization enforce a lot of adapting work
General Approach
Going along with the step-wise recommendation of the Visualization Pipeline, a prefuse application consists of different states of data:
prefuse uses a centralized object called Visualization (former ItemRegistry) which maintains and manages the whole visualization. This object has to fulfil several tasks. It stores the abstract data as well as visual analogous of these in two different tables. All transformation routines like filtering or rendering are maintained and executed by the Visualization too. Further, it maintains at least one Display, a graphical component which can represent visual data of prefuse.
Transformation routines are defined as Actions which are combined in ActionLists. An ActionList is an executable container which is started of the Visualization whenever necessary. Once it is started, all defined Actions are executed in the given sequence. Typically, the last called Action is the RepaintAction which forces all defined Displays to perform a repaint.
A Display is the view of prefuse. It can be embedded in each Java Swing application. The main task of a Display is the painting of visual structures which are defined in the respective Visualization. Whenever the Display performs a repaint it requests all visual items and checks all bounds of them (bounding management). If an item is within the own area the respective rendering mechanism is called.
Another important task of the Display is the providing of navigation techniques like zooming or panning. The entire view is managed by an own view coordinate system which is described with an affine transformation matrix. The most important functionality to work with this coordinate system is already predefined.
Furthermore, a Display also maintains a set of ControlListener which are used to process user interactions (mouse or keyboard events). Whenever such an event occurs the respective listener is called. This listener already differs on where the event happened (e.g., blank area or a certain item). Further, a ControlListener may also start an ActionList again.
Raw Data
Raw data is the base of the application. Typically, the source of raw data is a file, but also other sources like a database are thinkable. However, prefuse provides several file readers for different formats (CSV, Tab-Delimitated, etc.) that can be transformed into a data table. Further, some readers also support the reading of SQL-Database. If another source is needed, a reader can be written manually.
Once the raw data is read, it is transformed into abstract data and stored within a data table.
Abstract Data
The data table which is used to store abstract data works with data types and a definition schema which maps relations between data type and table. That means, each row contains a data record, and each column contains data values for a named data field with a specific data type. Each record of the table is referred as a Tuple.
Furthermore, instead of the table itself, a graph or tree may be used to store interrelated data. Instead of Tuples, records are referred as Nodes which are connected to others with Edges. Additionally, a tree has one defined root Node.
Abstract data does not contain any visual information like assignment attributes or color settings. Instead, visual attributes are extracted out of the abstract data following a defined logic.
Visual Structures
Visual structures are created when filtering the data container which contains abstract data. In case of a visualization that displays all items from the beginning on, the filtering routine must only executed once at initializing time. If the visual content changes dynamically, the filtering is executed on certain user interactions by calling a defined filtering ActionList.
A visual structure is referred as VisualItem which may distinguished as VisualNode, VisualEdge, or an aggregated item which consists of several other items. However, as a VisualItem is extended of the respective abstract entity it has full access to all abstract information too.
The filtering routine which transforms the abstract data to visual analogues typically consists of following Actions:
- Filter: This Action is responsible to transform the abstract data of the backing table to visual analogues. If no special conditions are defined, the filter creates for each Tuple a visual instance and stores them in a second table. Additionally, a filter also performs a garbage collection and may set visibility attributes of the created items.
- Layout: A layout takes care about placing the VisualItems. Several common algorithms for graphs or trees are already predefined (e.g., ForceDirectedLayout or RadialTreeLayout).
- Assignment: Besides layouting, also other assignments may be performed during the filtering process. Such assignments directly changes visual attributes of VisualItems like color, sizes, fonts, etc.
A visual structure may also contain a paint routine, but, as all painting jobs are initialized or performed by separated renderers, these issues may also be executed by the renderer itself or any other object.
View
Typically, the rendered visual structure is not stored, instead, they are re-rendered whenever needed. However, in case of very complex but constant visual representations it makes sense to hold items in an offscreen image.
Each VisualItem has got one or more associated Renderers which are maintained by a factory of the Visualization. A Render has to perform two tasks:
- Providing a bounding box of the item. This box is used to determine if the item must actually be painted or if it would not be visible anyway.
- Providing the painting routine of the item. Paintings may be executed by the Renderer itself or delegated to other objects which are accessible of the Renderer. The painting routines are not restricted in any way, but they representation should not exceed the bounding box of the item.
Rendering is always performed on a repaint of the Display. A repaint can be requested by the Visualization, on user interaction, and on events like resizing the component, getting the focus, or changing the coordinate system of the view. However, as repaints may occur very often, developers have to ascertain that rendering jobs can are performed fast, otherwise, the performance of the whole visualization would suffer.
Details
Package Structure
Following picture shows the most important packages of prefuse regarding to the Visualization Pipeline:
These packages also contain predefined components. A default nodes and edges provide standard functionality of abstract data, standard functionality is also available in visual analogous of them. A default filter transforms all defined abstract entities to visual ones. Further, also some special functionality for common requirements are provided by own components.
- Renderers: EdgeRenderer to render edges between graph or tree nodes, a LableRenderer to render test items, and a PolygoneRenderer to render geometrical items.
- Layouts: RandomLayout, GridLayout, and some more to place non related data, ForceDirectedLayout, TreeLayout, RadialTreeLayout and others to render trees and graphs.
- Controls: DragControl, ZoomControl, PanControl, ToolTipControl and several others to react on user interactions.
In simple visualizations the predefined functionality will meet most requirements. If special requirements are needed the default functionality supports a step-wise developing as results can be communicated by these components until the own functionality is implemented.
Coordinates in prefuse
prefuse works with two different coordinate systems. Absolute coordinates are device-independent logical coordinates. All visual attributes like positions or sizes are defined in absolute coordinates. In contrast, view coordinates are device-depended (screen). Transformations between absolute and view coordinates are done automatically by Java painting routines. View coordinates are influenced by the system and device driver (e.g., the absolute point (0,0) is the topmost left point of the actual graphical component which may be on any position at the screen). Further, view coordinates may also be manipulated manually by using an affine transformation matrix which applies linear transformations on absolute coordinates before device-dependent routines convert them to screen coordinates.
A prefuse Display provides the most important manipulating methods of this matrix. Zooming, panning, and rotation of the whole view are only done by changing the view coordinates. So, as absolute coordinates are never concerned of such transformations and translations, a user must never consider the actual view in layout, assignment, or painting routines.
There are several different ways on how to apply such transformations, additionally, the Display also supports animated transformations.
User Interactions
Mouse or keyboard events are treated by using ControlListener. Whenever an event occurs which is handled by a ControlListener, the Display delegates the event to the respective routine. A ControlListener differs automatically which visual element is concerned of the event (the view itself or a VisualItem on the view).
A ControlListener may just perform simple task like changing the mouse cursor or editing the label of an item. But, in more sophisticated applications, also task like loading new data or dragging items on the view may also be handled. Therefore, a ControlListener may also work with ActionLists to execute such tasks. Further, a ControlListener has also access to the Display to call methods like zooming or panning. Typically, each ControlListener forces a repaint when its job is done.
Most of standard functionality is already predefined in prefuse and the wanted listeners just have to be set to the Display. However, the Display can handle a countless of different listener. Hence, typically only a few listeners must be defined manually as they can be mixed with default ones.
Conclusion
prefuse is a very powerful toolkit, providing a large set of components and methods a developer needs to build an Information Visualization. The polylithic design is not that easy to understand in the beginning of a development, but once conceived, a visualization is easy to realize even if really special demands have to be fulfilled. Furthermore, using Prefuse forces a clear and well designed architecture of own applications.
prefuse was created with most attention paid to developers who will finally work with the toolkit. In an evaluation study this goal was approved too. In the meanwhile, there is also a not so small community using and upgrading the toolkit, which is an argue for its usability.
External links
References
- [Heer, 2004] Jeffrey Heer. prefuse: a software framework for interactive information visualization. Masters of Science, Computer Science Division, University of California, Berkeley, 2004.
- [Heer, 2005] Jeffrey Heer, Stuart K. Card, and James A. Landay. prefuse: a toolkit for interactive information visualization. In CHI 2005, Human Factors in Computing Systems, 2005.
- [Heer, 2006a] Jeffrey Heer, prefuse API documentation, Retrieved at: July 06, 2006, http://prefuse.org
- [Heer, 2006b] Jeffrey Heer, prefuse manual, Retrieved at: July 06, 2006, http://prefuse.org
- [Sun Microsystems, 2001] Sun Microsystems, Programmer’s Guide to the Java 2DTM API - Enhanced Graphics and Imaging for Java, Retrieved at: April 20, 2006, http://java.sun.com/j2se/1.4/pdf/j2d-book.pdf