Index: /trunk/sources/HeuristicLab.Visualization.Test/3.2/LegendForm.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization.Test/3.2/LegendForm.Designer.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization.Test/3.2/LegendForm.Designer.cs	(revision 1964)
@@ -1,3 +1,5 @@
-﻿namespace HeuristicLab.Visualization.Test {
+﻿using HeuristicLab.Visualization.Drawing;
+
+namespace HeuristicLab.Visualization.Test {
   partial class LegendForm {
     /// <summary>
@@ -24,5 +26,5 @@
     /// </summary>
     private void InitializeComponent() {
-      this.canvasUI = new HeuristicLab.Visualization.CanvasUI();
+      this.canvasUI = new CanvasUI();
       this.SuspendLayout();
       // 
Index: /trunk/sources/HeuristicLab.Visualization.Test/3.2/MainForm.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization.Test/3.2/MainForm.Designer.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization.Test/3.2/MainForm.Designer.cs	(revision 1964)
@@ -1,3 +1,5 @@
-﻿namespace HeuristicLab.Visualization.Test {
+﻿using HeuristicLab.Visualization.Drawing;
+
+namespace HeuristicLab.Visualization.Test {
   partial class MainForm {
     /// <summary>
@@ -24,5 +26,5 @@
     /// </summary>
     private void InitializeComponent() {
-      this.canvasUI = new HeuristicLab.Visualization.CanvasUI();
+      this.canvasUI = new CanvasUI();
       this.label2 = new System.Windows.Forms.Label();
       this.legendButton = new System.Windows.Forms.Button();
@@ -73,5 +75,5 @@
     #endregion
 
-    private HeuristicLab.Visualization.CanvasUI canvasUI;
+    private CanvasUI canvasUI;
     private System.Windows.Forms.Label label2;
     private System.Windows.Forms.Button legendButton;
Index: /trunk/sources/HeuristicLab.Visualization.Test/3.2/MainForm.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization.Test/3.2/MainForm.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization.Test/3.2/MainForm.cs	(revision 1964)
@@ -2,4 +2,5 @@
 using System.Drawing;
 using System.Windows.Forms;
+using HeuristicLab.Visualization.Drawing;
 
 namespace HeuristicLab.Visualization.Test {
Index: unk/sources/HeuristicLab.Visualization/3.2/Canvas.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/Canvas.cs	(revision 1963)
+++ 	(revision )
@@ -1,77 +1,0 @@
-using System;
-using System.Diagnostics;
-using System.Drawing;
-using System.Drawing.Drawing2D;
-
-namespace HeuristicLab.Visualization {
-  public class Canvas : IShape {
-    private readonly WorldShape worldShape;
-
-    private Rectangle viewport;
-
-    public Canvas() {
-      worldShape = new WorldShape();
-      worldShape.Parent = this;
-    }
-
-    public void AddShape(IShape shape) {
-      worldShape.AddShape(shape);
-    }
-
-    public void RemoveShape(IShape shape) {
-      worldShape.RemoveShape(shape);
-    }
-
-    public void ClearShapes() {
-      worldShape.ClearShapes();
-    }
-
-    public Rectangle Viewport {
-      get { return viewport; }
-      set {
-        viewport = value;
-        worldShape.ClippingArea = new RectangleD(0, 0, viewport.Width, viewport.Height);
-        worldShape.BoundingBox = worldShape.ClippingArea;
-      }
-    }
-
-    public RectangleD ClippingArea {
-      get { return worldShape.ClippingArea; }
-    }
-
-    public RectangleD BoundingBox {
-      get { throw new InvalidOperationException(); }
-    }
-
-    public IShape Parent {
-      get { throw new InvalidOperationException(); }
-      set { throw new InvalidOperationException(); }
-    }
-
-    public void Draw(Graphics graphics) {
-      try {
-        Stopwatch sw = new Stopwatch();
-        sw.Start();
-
-        graphics.SmoothingMode = SmoothingMode.AntiAlias;
-        graphics.FillRectangle(Brushes.White, Viewport);
-
-        worldShape.Draw(graphics);
-
-        graphics.DrawRectangle(Pens.Black, 0, 0, Viewport.Width - 1, Viewport.Height - 1);
-
-        sw.Stop();
-        Trace.WriteLine(string.Format("Drawing time: {0:0.0}ms", sw.Elapsed.TotalMilliseconds));
-      } catch (OverflowException e) {
-        Trace.WriteLine(e);
-
-        graphics.FillRectangle(Brushes.White, graphics.ClipBounds);
-
-        using (Font font = new Font("Arial", 14)) {
-          const string message = "Zoom level is too high!";
-          graphics.DrawString(message, font, Brushes.Red, graphics.ClipBounds.X + 10, graphics.ClipBounds.Y + 10);
-        }
-      }
-    }
-  }
-}
Index: unk/sources/HeuristicLab.Visualization/3.2/CanvasUI.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/CanvasUI.Designer.cs	(revision 1963)
+++ 	(revision )
@@ -1,41 +1,0 @@
-﻿namespace HeuristicLab.Visualization
-{
-    partial class CanvasUI
-    {
-        /// <summary>
-        /// Required designer variable.
-        /// </summary>
-        private System.ComponentModel.IContainer components = null;
-
-        /// <summary>
-        /// Clean up any resources being used.
-        /// </summary>
-        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing && (components != null))
-            {
-                components.Dispose();
-            }
-            base.Dispose(disposing);
-        }
-
-        #region Component Designer generated code
-
-        /// <summary>
-        /// Required method for Designer support - do not modify 
-        /// the contents of this method with the code editor.
-        /// </summary>
-        private void InitializeComponent()
-        {
-          this.SuspendLayout();
-          // 
-          // CanvasUI
-          // 
-          this.ResumeLayout(false);
-
-        }
-
-        #endregion
-    }
-}
Index: unk/sources/HeuristicLab.Visualization/3.2/CanvasUI.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/CanvasUI.cs	(revision 1963)
+++ 	(revision )
@@ -1,50 +1,0 @@
-﻿using System;
-using System.Diagnostics;
-using System.Drawing;
-using System.Windows.Forms;
-
-namespace HeuristicLab.Visualization {
-  public partial class CanvasUI : Control {
-    private readonly Canvas canvas = new Canvas();
-
-    public CanvasUI() {
-      InitializeComponent();
-
-      DoubleBuffered = true;
-    }
-
-    public Canvas Canvas {
-      get { return canvas; }
-    }
-
-    public event PaintEventHandler BeforePaint;
-
-    protected override void OnPaint(PaintEventArgs pe) {
-      try {
-        FireBeforePaint(pe);
-
-        Graphics g = pe.Graphics;
-
-        canvas.Viewport = ClientRectangle;
-        canvas.Draw(g);
-
-        base.OnPaint(pe);
-      } catch (Exception e) {
-       Trace.WriteLine(e);
-      }
-    }
-
-    protected override void OnResize(EventArgs e) {
-      Invalidate();
-
-      canvas.Viewport = ClientRectangle;
-
-      base.OnResize(e);
-    }
-
-    private void FireBeforePaint(PaintEventArgs e) {
-      if (BeforePaint != null)
-        BeforePaint(this, e);
-    }
-  }
-}
Index: unk/sources/HeuristicLab.Visualization/3.2/CompositeShape.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/CompositeShape.cs	(revision 1963)
+++ 	(revision )
@@ -1,102 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Drawing;
-
-namespace HeuristicLab.Visualization {
-  public class CompositeShape : IShape {
-    private IShape parent;
-    private bool showChildShapes = true;
-
-    protected readonly List<IShape> shapes = new List<IShape>();
-    protected RectangleD boundingBox = RectangleD.Empty;
-
-
-
-    public virtual void Draw(Graphics graphics) {
-      if(!showChildShapes)
-        return;
-      foreach (IShape shape in shapes) {
-        shape.Draw(graphics);
-      }
-    }
-
-    public RectangleD BoundingBox {
-      get {
-        if (shapes.Count == 0) {
-          throw new InvalidOperationException("No shapes, no bounding box.");
-        }
-
-        return boundingBox;
-      }
-    }
-
-    public RectangleD ClippingArea {
-      get { return Parent.ClippingArea; }
-    }
-
-    public Rectangle Viewport {
-      get { return Parent.Viewport; }
-    }
-
-    public IShape Parent {
-      get { return parent; }
-      set { parent = value; }
-    }
-
-    public bool ShowChildShapes {
-      get { return showChildShapes; }
-      set { showChildShapes = value; }
-    }
-
-    public void ClearShapes() {
-      shapes.Clear();
-      boundingBox = RectangleD.Empty;
-    }
-
-    public IShape GetShape(int index) {
-      return shapes[index];
-    }
-
-
-    /// <summary>
-    /// Adds a shape to the container
-    /// </summary>
-    /// <param name="shape"> the Shape to add</param>
-    public void AddShape(IShape shape) {
-      shape.Parent = this;
-
-      if (shapes.Count == 0) {
-        boundingBox = shape.BoundingBox;
-      } else {
-        boundingBox = new RectangleD(Math.Min(boundingBox.X1, shape.BoundingBox.X1),
-                                     Math.Min(boundingBox.Y1, shape.BoundingBox.Y1),
-                                     Math.Max(boundingBox.X2, shape.BoundingBox.X2),
-                                     Math.Max(boundingBox.Y2, shape.BoundingBox.Y2));
-      }
-      shapes.Add(shape);
-    }
-
-    /// <summary>
-    /// Recalculate the bounding box
-    /// </summary>
-    private void InitBoundingBox() {
-      if (shapes.Count > 0) 
-        boundingBox = shapes[0].BoundingBox;
-      foreach (var shape in shapes) {
-        boundingBox = new RectangleD(Math.Min(boundingBox.X1, shape.BoundingBox.X1),
-                                    Math.Min(boundingBox.Y1, shape.BoundingBox.Y1),
-                                    Math.Max(boundingBox.X2, shape.BoundingBox.X2),
-                                    Math.Max(boundingBox.Y2, shape.BoundingBox.Y2));
-      }
-    }
-
-    /// <summary>
-    /// Removes a Shape from the container and reinitializes the bounding box
-    /// </summary>
-    /// <param name="shape">the Shape to remove</param>
-    public void RemoveShape(IShape shape) {
-      shapes.Remove(shape);
-      InitBoundingBox();
-    }
-  }
-}
Index: /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/Canvas.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/Canvas.cs	(revision 1964)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/Canvas.cs	(revision 1964)
@@ -0,0 +1,77 @@
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+namespace HeuristicLab.Visualization.Drawing {
+  public class Canvas : IShape {
+    private readonly WorldShape worldShape;
+
+    private Rectangle viewport;
+
+    public Canvas() {
+      worldShape = new WorldShape();
+      worldShape.Parent = this;
+    }
+
+    public void AddShape(IShape shape) {
+      worldShape.AddShape(shape);
+    }
+
+    public void RemoveShape(IShape shape) {
+      worldShape.RemoveShape(shape);
+    }
+
+    public void ClearShapes() {
+      worldShape.ClearShapes();
+    }
+
+    public Rectangle Viewport {
+      get { return viewport; }
+      set {
+        viewport = value;
+        worldShape.ClippingArea = new RectangleD(0, 0, viewport.Width, viewport.Height);
+        worldShape.BoundingBox = worldShape.ClippingArea;
+      }
+    }
+
+    public RectangleD ClippingArea {
+      get { return worldShape.ClippingArea; }
+    }
+
+    public RectangleD BoundingBox {
+      get { throw new InvalidOperationException(); }
+    }
+
+    public IShape Parent {
+      get { throw new InvalidOperationException(); }
+      set { throw new InvalidOperationException(); }
+    }
+
+    public void Draw(Graphics graphics) {
+      try {
+        Stopwatch sw = new Stopwatch();
+        sw.Start();
+
+        graphics.SmoothingMode = SmoothingMode.AntiAlias;
+        graphics.FillRectangle(Brushes.White, Viewport);
+
+        worldShape.Draw(graphics);
+
+        graphics.DrawRectangle(Pens.Black, 0, 0, Viewport.Width - 1, Viewport.Height - 1);
+
+        sw.Stop();
+        Trace.WriteLine(string.Format("Drawing time: {0:0.0}ms", sw.Elapsed.TotalMilliseconds));
+      } catch (OverflowException e) {
+        Trace.WriteLine(e);
+
+        graphics.FillRectangle(Brushes.White, graphics.ClipBounds);
+
+        using (Font font = new Font("Arial", 14)) {
+          const string message = "Zoom level is too high!";
+          graphics.DrawString(message, font, Brushes.Red, graphics.ClipBounds.X + 10, graphics.ClipBounds.Y + 10);
+        }
+      }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/CanvasUI.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/CanvasUI.Designer.cs	(revision 1964)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/CanvasUI.Designer.cs	(revision 1964)
@@ -0,0 +1,40 @@
+﻿namespace HeuristicLab.Visualization.Drawing {
+  partial class CanvasUI
+  {
+    /// <summary>
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary>
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing)
+    {
+      if (disposing && (components != null))
+      {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary>
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent()
+    {
+      this.SuspendLayout();
+      // 
+      // CanvasUI
+      // 
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/CanvasUI.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/CanvasUI.cs	(revision 1964)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/CanvasUI.cs	(revision 1964)
@@ -0,0 +1,50 @@
+﻿using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace HeuristicLab.Visualization.Drawing {
+  public partial class CanvasUI : Control {
+    private readonly Canvas canvas = new Canvas();
+
+    public CanvasUI() {
+      InitializeComponent();
+
+      DoubleBuffered = true;
+    }
+
+    public Canvas Canvas {
+      get { return canvas; }
+    }
+
+    public event PaintEventHandler BeforePaint;
+
+    protected override void OnPaint(PaintEventArgs pe) {
+      try {
+        FireBeforePaint(pe);
+
+        Graphics g = pe.Graphics;
+
+        canvas.Viewport = ClientRectangle;
+        canvas.Draw(g);
+
+        base.OnPaint(pe);
+      } catch (Exception e) {
+        Trace.WriteLine(e);
+      }
+    }
+
+    protected override void OnResize(EventArgs e) {
+      Invalidate();
+
+      canvas.Viewport = ClientRectangle;
+
+      base.OnResize(e);
+    }
+
+    private void FireBeforePaint(PaintEventArgs e) {
+      if (BeforePaint != null)
+        BeforePaint(this, e);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/CompositeShape.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/CompositeShape.cs	(revision 1964)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/CompositeShape.cs	(revision 1964)
@@ -0,0 +1,102 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace HeuristicLab.Visualization.Drawing {
+  public class CompositeShape : IShape {
+    private IShape parent;
+    private bool showChildShapes = true;
+
+    protected readonly List<IShape> shapes = new List<IShape>();
+    protected RectangleD boundingBox = RectangleD.Empty;
+
+
+
+    public virtual void Draw(Graphics graphics) {
+      if(!showChildShapes)
+        return;
+      foreach (IShape shape in shapes) {
+        shape.Draw(graphics);
+      }
+    }
+
+    public RectangleD BoundingBox {
+      get {
+        if (shapes.Count == 0) {
+          throw new InvalidOperationException("No shapes, no bounding box.");
+        }
+
+        return boundingBox;
+      }
+    }
+
+    public RectangleD ClippingArea {
+      get { return Parent.ClippingArea; }
+    }
+
+    public Rectangle Viewport {
+      get { return Parent.Viewport; }
+    }
+
+    public IShape Parent {
+      get { return parent; }
+      set { parent = value; }
+    }
+
+    public bool ShowChildShapes {
+      get { return showChildShapes; }
+      set { showChildShapes = value; }
+    }
+
+    public void ClearShapes() {
+      shapes.Clear();
+      boundingBox = RectangleD.Empty;
+    }
+
+    public IShape GetShape(int index) {
+      return shapes[index];
+    }
+
+
+    /// <summary>
+    /// Adds a shape to the container
+    /// </summary>
+    /// <param name="shape"> the Shape to add</param>
+    public void AddShape(IShape shape) {
+      shape.Parent = this;
+
+      if (shapes.Count == 0) {
+        boundingBox = shape.BoundingBox;
+      } else {
+        boundingBox = new RectangleD(Math.Min(boundingBox.X1, shape.BoundingBox.X1),
+                                     Math.Min(boundingBox.Y1, shape.BoundingBox.Y1),
+                                     Math.Max(boundingBox.X2, shape.BoundingBox.X2),
+                                     Math.Max(boundingBox.Y2, shape.BoundingBox.Y2));
+      }
+      shapes.Add(shape);
+    }
+
+    /// <summary>
+    /// Recalculate the bounding box
+    /// </summary>
+    private void InitBoundingBox() {
+      if (shapes.Count > 0) 
+        boundingBox = shapes[0].BoundingBox;
+      foreach (var shape in shapes) {
+        boundingBox = new RectangleD(Math.Min(boundingBox.X1, shape.BoundingBox.X1),
+                                     Math.Min(boundingBox.Y1, shape.BoundingBox.Y1),
+                                     Math.Max(boundingBox.X2, shape.BoundingBox.X2),
+                                     Math.Max(boundingBox.Y2, shape.BoundingBox.Y2));
+      }
+    }
+
+    /// <summary>
+    /// Removes a Shape from the container and reinitializes the bounding box
+    /// </summary>
+    /// <param name="shape">the Shape to remove</param>
+    public void RemoveShape(IShape shape) {
+      shapes.Remove(shape);
+      InitBoundingBox();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/IShape.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/IShape.cs	(revision 1964)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/IShape.cs	(revision 1964)
@@ -0,0 +1,39 @@
+using System.Drawing;
+
+namespace HeuristicLab.Visualization.Drawing {
+  /// <summary>
+  /// This is the base interface that has to be implemented by all shapes.
+  /// 
+  /// View port
+  ///   The view port is the available drawing area on the screen.
+  ///   It is specified in the GDI coordinate system.
+  /// 
+  /// Clipping area
+  ///   The clipping area is the range of values visible on the view port.
+  ///   Values outside this area will not be visible (they "get clipped").
+  ///   It can either be inherited from the parent, or it can be overriden
+  ///   to create distorted realities (see world shapes).
+  ///   It is specified in a world coordinate system.
+  /// 
+  /// Bounding box
+  ///   The bounding box is the location and the size of a shape on its parent.
+  ///   It is specified in the parent's world coordinate system.
+  /// </summary>
+  public interface IShape {
+    /// <summary>
+    /// Draws the shape
+    /// </summary>
+    /// <param name="graphics">The Graphics object used to draw the shape</param>
+    void Draw(Graphics graphics);
+
+    /// <summary>
+    /// The shape's bounding box
+    /// </summary>
+    RectangleD BoundingBox { get; }
+
+    RectangleD ClippingArea { get; }
+    Rectangle Viewport { get; }
+
+    IShape Parent { get; set; }
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/Transform.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/Transform.cs	(revision 1964)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/Transform.cs	(revision 1964)
@@ -0,0 +1,117 @@
+﻿using System.Drawing;
+
+namespace HeuristicLab.Visualization.Drawing {
+  /// <summary>
+  /// GDI (or screen) coordinate system
+  ///   The GDI coordinate system is specified in pixels. X goes from left to right
+  ///   and Y goes from top to bottom.
+  /// 
+  /// World coordinate system
+  ///   A world coordinate system can be freely specified. X goes from left to
+  ///   right and Y goes from bottom to top.
+  /// 
+  /// The transformation between world- and screen-coordinate systems is done using
+  /// a view port and a clipping area.
+  /// </summary>
+  public static class Transform {
+    /// <summary>
+    /// Transforms a rectangle in screen coordinates to world coordinates
+    /// </summary>
+    /// <param name="rect">The rectangle in screen coordinates that should be transformed</param>
+    /// <param name="viewport">The target view port</param>
+    /// <param name="clippingArea">The target clipping area</param>
+    /// <returns>The rectangle rect transformed to world coordinates</returns>
+    public static RectangleD ToWorld(Rectangle rect, Rectangle viewport, RectangleD clippingArea) {
+      double x1 = ToWorldX(rect.Left, viewport, clippingArea);
+      double y1 = ToWorldY(rect.Bottom, viewport, clippingArea);
+      double x2 = ToWorldX(rect.Right, viewport, clippingArea);
+      double y2 = ToWorldY(rect.Top, viewport, clippingArea);
+      return new RectangleD(x1, y1, x2, y2);
+    }
+
+    /// <summary>
+    /// Transforms a 2d point in screen coordinates to world coordinates
+    /// </summary>
+    /// <param name="point">The point in screen coordinates that should be transformed</param>
+    /// <param name="viewport">The target view port</param>
+    /// <param name="clippingArea">The target clipping area</param>
+    /// <returns>The point transformed to world coordinates</returns>
+    public static PointD ToWorld(Point point, Rectangle viewport, RectangleD clippingArea) {
+      double x = ToWorldX(point.X, viewport, clippingArea);
+      double y = ToWorldY(point.Y, viewport, clippingArea);
+      return new PointD(x, y);
+    }
+
+    /// <summary>
+    /// Transforms a point on the X-axis in screen coordinates to world coordinates
+    /// </summary>
+    /// <param name="x">The point on the X-axis in screen coordinates that should be transformed</param>
+    /// <param name="viewport">The target view port</param>
+    /// <param name="clippingArea">The target clipping area</param>
+    /// <returns>The point transformed to world coordinates</returns>
+    public static double ToWorldX(int x, Rectangle viewport, RectangleD clippingArea) {
+      return clippingArea.X1 + clippingArea.Width/viewport.Width*(x - viewport.Left);
+    }
+
+    /// <summary>
+    /// Transforms a point on the Y-axis in screen coordinates to world coordinates
+    /// </summary>
+    /// <param name="y">The point on the Y-axis in screen coordinates that should be transformed</param>
+    /// <param name="viewport">The target view port</param>
+    /// <param name="clippingArea">The target clipping area</param>
+    /// <returns>The point transformed to world coordinates</returns>
+    public static double ToWorldY(int y, Rectangle viewport, RectangleD clippingArea) {
+      return clippingArea.Y1 - clippingArea.Height/viewport.Height*(y - viewport.Bottom);
+    }
+
+    /// <summary>
+    /// Transforms a rectangle in world coordinates to screen coordinates
+    /// </summary>
+    /// <param name="rect">The rectangle in world coordinates that should be transformed</param>
+    /// <param name="viewport">The target view port</param>
+    /// <param name="clippingArea">The target clipping area</param>
+    /// <returns>The rectangle rect transformed to screen coordinates</returns>
+    public static Rectangle ToScreen(RectangleD rect, Rectangle viewport, RectangleD clippingArea) {
+      int left = ToScreenX(rect.X1, viewport, clippingArea);
+      int bottom = ToScreenY(rect.Y1, viewport, clippingArea);
+      int right = ToScreenX(rect.X2, viewport, clippingArea);
+      int top = ToScreenY(rect.Y2, viewport, clippingArea);
+      return new Rectangle(left, top, right - left , bottom - top );
+    }
+
+    /// <summary>
+    /// Transforms a 2d point in world coordinates to screen coordinates
+    /// </summary>
+    /// <param name="point">The point in world coordinates that should be transformed</param>
+    /// <param name="viewport">The target view port</param>
+    /// <param name="clippingArea">The target clipping area</param>
+    /// <returns>The point transformed to screen coordinates</returns>
+    public static Point ToScreen(PointD point, Rectangle viewport, RectangleD clippingArea) {
+      int x = ToScreenX(point.X, viewport, clippingArea);
+      int y = ToScreenY(point.Y, viewport, clippingArea);
+      return new Point(x, y);
+    }
+
+    /// <summary>
+    /// Transforms a point on the X-axis in world coordinates to screen coordinates
+    /// </summary>
+    /// <param name="x">The point on the X-axis in world coordinates that should be transformed</param>
+    /// <param name="viewport">The target view port</param>
+    /// <param name="clippingArea">The target clipping area</param>
+    /// <returns>The point transformed to screen coordinates</returns>
+    public static int ToScreenX(double x, Rectangle viewport, RectangleD clippingArea) {
+      return (int)(viewport.Left + viewport.Width/clippingArea.Width*(x - clippingArea.X1));
+    }
+
+    /// <summary>
+    /// Transforms a point on the Y-axis in world coordinates to screen coordinates
+    /// </summary>
+    /// <param name="y">The point on the Y-axis in world coordinates that should be transformed</param>
+    /// <param name="viewport">The target view port</param>
+    /// <param name="clippingArea">The target clipping area</param>
+    /// <returns>The point transformed to screen coordinates</returns>
+    public static int ToScreenY(double y, Rectangle viewport, RectangleD clippingArea) {
+      return (int)(viewport.Bottom - viewport.Height/clippingArea.Height*(y - clippingArea.Y1));
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/WorldShape.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/WorldShape.cs	(revision 1964)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/Drawing/WorldShape.cs	(revision 1964)
@@ -0,0 +1,77 @@
+﻿using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+namespace HeuristicLab.Visualization.Drawing {
+  /// <summary>
+  /// World shapes are composite shapes that have their own coordinate system
+  /// which is independent from their parent's coordinate system.
+  /// </summary>
+  public class WorldShape : IShape {
+    private RectangleD clippingArea; // own clipping area
+    private RectangleD boundingBox;
+    private IShape parent;
+
+    protected readonly List<IShape> shapes = new List<IShape>();
+
+    public WorldShape() {
+      this.clippingArea = new RectangleD(0, 0, 1, 1);
+      this.boundingBox = new RectangleD(0, 0, 1, 1);
+    }
+
+    public virtual void Draw(Graphics graphics) {
+      GraphicsState gstate = graphics.Save();
+
+      graphics.SetClip(Viewport);
+
+      foreach (IShape shape in shapes) {
+        // draw child shapes using our own clipping area
+        shape.Draw(graphics);
+      }
+
+      graphics.Restore(gstate);
+    }
+
+    public RectangleD BoundingBox {
+      get { return boundingBox; }
+      set { boundingBox = value; }
+    }
+
+    /// <summary>
+    /// The world shape's own clipping area.
+    /// This overrides the clipping area of the parent shape.
+    /// </summary>
+    public RectangleD ClippingArea {
+      get { return clippingArea; }
+      set { clippingArea = value; }
+    }
+
+    public Rectangle Viewport {
+      get {
+        // calculate our drawing area on the screen using our location and
+        // size in the parent (boundingBox), the parent's viewport and the
+        // parent's clipping area
+        Rectangle viewport = Transform.ToScreen(boundingBox, Parent.Viewport, Parent.ClippingArea);
+        return viewport;
+      }
+    }
+
+    public IShape Parent {
+      get { return parent; }
+      set { parent = value; }
+    }
+
+    public void ClearShapes() {
+      shapes.Clear();
+    }
+
+    public void AddShape(IShape shape) {
+      shape.Parent = this;
+      shapes.Add(shape);
+    }
+
+    public bool RemoveShape(IShape shape) {
+      return shapes.Remove(shape);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization/3.2/HeuristicLab.Visualization-3.2.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/HeuristicLab.Visualization-3.2.csproj	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/HeuristicLab.Visualization-3.2.csproj	(revision 1964)
@@ -89,9 +89,9 @@
     <Compile Include="AxisPosition.cs" />
     <Compile Include="AxisTicks.cs" />
-    <Compile Include="Canvas.cs" />
-    <Compile Include="CanvasUI.cs">
+    <Compile Include="Drawing\Canvas.cs" />
+    <Compile Include="Drawing\CanvasUI.cs">
       <SubType>Component</SubType>
     </Compile>
-    <Compile Include="CanvasUI.Designer.cs">
+    <Compile Include="Drawing\CanvasUI.Designer.cs">
       <DependentUpon>CanvasUI.cs</DependentUpon>
     </Compile>
@@ -99,5 +99,5 @@
     <Compile Include="ChartDataRowsModel.cs" />
     <Compile Include="ChartDataRowsModelDummy.cs" />
-    <Compile Include="CompositeShape.cs" />
+    <Compile Include="Drawing\CompositeShape.cs" />
     <Compile Include="ChartDataRowsModelDataCollector.cs" />
     <Compile Include="DataExport\CSVDataExport.cs" />
@@ -152,5 +152,5 @@
     <Compile Include="IChartDataRowsModel.cs" />
     <Compile Include="IDataRow.cs" />
-    <Compile Include="IShape.cs" />
+    <Compile Include="Drawing\IShape.cs" />
     <Compile Include="LineChart.cs">
       <SubType>UserControl</SubType>
@@ -167,7 +167,7 @@
     <Compile Include="SizeD.cs" />
     <Compile Include="TooltipListener.cs" />
-    <Compile Include="Transform.cs" />
+    <Compile Include="Drawing\Transform.cs" />
     <Compile Include="Translate.cs" />
-    <Compile Include="WorldShape.cs" />
+    <Compile Include="Drawing\WorldShape.cs" />
     <Compile Include="XAxis.cs" />
     <Compile Include="XAxisGrid.cs" />
Index: unk/sources/HeuristicLab.Visualization/3.2/IShape.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/IShape.cs	(revision 1963)
+++ 	(revision )
@@ -1,39 +1,0 @@
-using System.Drawing;
-
-namespace HeuristicLab.Visualization {
-  /// <summary>
-  /// This is the base interface that has to be implemented by all shapes.
-  /// 
-  /// View port
-  ///   The view port is the available drawing area on the screen.
-  ///   It is specified in the GDI coordinate system.
-  /// 
-  /// Clipping area
-  ///   The clipping area is the range of values visible on the view port.
-  ///   Values outside this area will not be visible (they "get clipped").
-  ///   It can either be inherited from the parent, or it can be overriden
-  ///   to create distorted realities (see world shapes).
-  ///   It is specified in a world coordinate system.
-  /// 
-  /// Bounding box
-  ///   The bounding box is the location and the size of a shape on its parent.
-  ///   It is specified in the parent's world coordinate system.
-  /// </summary>
-  public interface IShape {
-    /// <summary>
-    /// Draws the shape
-    /// </summary>
-    /// <param name="graphics">The Graphics object used to draw the shape</param>
-    void Draw(Graphics graphics);
-
-    /// <summary>
-    /// The shape's bounding box
-    /// </summary>
-    RectangleD BoundingBox { get; }
-
-    RectangleD ClippingArea { get; }
-    Rectangle Viewport { get; }
-
-    IShape Parent { get; set; }
-  }
-}
Index: /trunk/sources/HeuristicLab.Visualization/3.2/Legend/LegendShape.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/Legend/LegendShape.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/Legend/LegendShape.cs	(revision 1964)
@@ -1,4 +1,5 @@
 using System.Collections.Generic;
 using System.Drawing;
+using HeuristicLab.Visualization.Drawing;
 
 namespace HeuristicLab.Visualization.Legend {
Index: /trunk/sources/HeuristicLab.Visualization/3.2/LineChart.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/LineChart.Designer.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/LineChart.Designer.cs	(revision 1964)
@@ -1,3 +1,4 @@
 ﻿using System.Windows.Forms;
+using HeuristicLab.Visualization.Drawing;
 
 namespace HeuristicLab.Visualization
@@ -32,5 +33,5 @@
         {
           this.components = new System.ComponentModel.Container();
-          this.canvasUI = new HeuristicLab.Visualization.CanvasUI();
+          this.canvasUI = new CanvasUI();
           this.contextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
           this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
Index: /trunk/sources/HeuristicLab.Visualization/3.2/LineChart.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/LineChart.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/LineChart.cs	(revision 1964)
@@ -6,4 +6,5 @@
 using HeuristicLab.Core;
 using HeuristicLab.Visualization.DataExport;
+using HeuristicLab.Visualization.Drawing;
 using HeuristicLab.Visualization.Legend;
 using HeuristicLab.Visualization.Options;
Index: /trunk/sources/HeuristicLab.Visualization/3.2/LineShape.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/LineShape.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/LineShape.cs	(revision 1964)
@@ -1,4 +1,5 @@
 ﻿using System.Drawing;
 using System.Drawing.Drawing2D;
+using HeuristicLab.Visualization.Drawing;
 
 namespace HeuristicLab.Visualization {
Index: /trunk/sources/HeuristicLab.Visualization/3.2/MarkerShape.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/MarkerShape.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/MarkerShape.cs	(revision 1964)
@@ -1,8 +1,5 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Drawing;
+﻿using System.Drawing;
 using System.Drawing.Drawing2D;
-using System.Linq;
-using System.Text;
+using HeuristicLab.Visualization.Drawing;
 
 namespace HeuristicLab.Visualization {
Index: /trunk/sources/HeuristicLab.Visualization/3.2/RectangleShape.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/RectangleShape.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/RectangleShape.cs	(revision 1964)
@@ -1,3 +1,4 @@
 using System.Drawing;
+using HeuristicLab.Visualization.Drawing;
 
 namespace HeuristicLab.Visualization {
Index: /trunk/sources/HeuristicLab.Visualization/3.2/TextShape.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/TextShape.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/TextShape.cs	(revision 1964)
@@ -2,4 +2,5 @@
 using System.Drawing;
 using System.Drawing.Drawing2D;
+using HeuristicLab.Visualization.Drawing;
 
 namespace HeuristicLab.Visualization {
Index: unk/sources/HeuristicLab.Visualization/3.2/Transform.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/Transform.cs	(revision 1963)
+++ 	(revision )
@@ -1,117 +1,0 @@
-﻿using System.Drawing;
-
-namespace HeuristicLab.Visualization {
-  /// <summary>
-  /// GDI (or screen) coordinate system
-  ///   The GDI coordinate system is specified in pixels. X goes from left to right
-  ///   and Y goes from top to bottom.
-  /// 
-  /// World coordinate system
-  ///   A world coordinate system can be freely specified. X goes from left to
-  ///   right and Y goes from bottom to top.
-  /// 
-  /// The transformation between world- and screen-coordinate systems is done using
-  /// a view port and a clipping area.
-  /// </summary>
-  public static class Transform {
-    /// <summary>
-    /// Transforms a rectangle in screen coordinates to world coordinates
-    /// </summary>
-    /// <param name="rect">The rectangle in screen coordinates that should be transformed</param>
-    /// <param name="viewport">The target view port</param>
-    /// <param name="clippingArea">The target clipping area</param>
-    /// <returns>The rectangle rect transformed to world coordinates</returns>
-    public static RectangleD ToWorld(Rectangle rect, Rectangle viewport, RectangleD clippingArea) {
-      double x1 = ToWorldX(rect.Left, viewport, clippingArea);
-      double y1 = ToWorldY(rect.Bottom, viewport, clippingArea);
-      double x2 = ToWorldX(rect.Right, viewport, clippingArea);
-      double y2 = ToWorldY(rect.Top, viewport, clippingArea);
-      return new RectangleD(x1, y1, x2, y2);
-    }
-
-    /// <summary>
-    /// Transforms a 2d point in screen coordinates to world coordinates
-    /// </summary>
-    /// <param name="point">The point in screen coordinates that should be transformed</param>
-    /// <param name="viewport">The target view port</param>
-    /// <param name="clippingArea">The target clipping area</param>
-    /// <returns>The point transformed to world coordinates</returns>
-    public static PointD ToWorld(Point point, Rectangle viewport, RectangleD clippingArea) {
-      double x = ToWorldX(point.X, viewport, clippingArea);
-      double y = ToWorldY(point.Y, viewport, clippingArea);
-      return new PointD(x, y);
-    }
-
-    /// <summary>
-    /// Transforms a point on the X-axis in screen coordinates to world coordinates
-    /// </summary>
-    /// <param name="x">The point on the X-axis in screen coordinates that should be transformed</param>
-    /// <param name="viewport">The target view port</param>
-    /// <param name="clippingArea">The target clipping area</param>
-    /// <returns>The point transformed to world coordinates</returns>
-    public static double ToWorldX(int x, Rectangle viewport, RectangleD clippingArea) {
-      return clippingArea.X1 + clippingArea.Width/viewport.Width*(x - viewport.Left);
-    }
-
-    /// <summary>
-    /// Transforms a point on the Y-axis in screen coordinates to world coordinates
-    /// </summary>
-    /// <param name="y">The point on the Y-axis in screen coordinates that should be transformed</param>
-    /// <param name="viewport">The target view port</param>
-    /// <param name="clippingArea">The target clipping area</param>
-    /// <returns>The point transformed to world coordinates</returns>
-    public static double ToWorldY(int y, Rectangle viewport, RectangleD clippingArea) {
-      return clippingArea.Y1 - clippingArea.Height/viewport.Height*(y - viewport.Bottom);
-    }
-
-    /// <summary>
-    /// Transforms a rectangle in world coordinates to screen coordinates
-    /// </summary>
-    /// <param name="rect">The rectangle in world coordinates that should be transformed</param>
-    /// <param name="viewport">The target view port</param>
-    /// <param name="clippingArea">The target clipping area</param>
-    /// <returns>The rectangle rect transformed to screen coordinates</returns>
-    public static Rectangle ToScreen(RectangleD rect, Rectangle viewport, RectangleD clippingArea) {
-      int left = ToScreenX(rect.X1, viewport, clippingArea);
-      int bottom = ToScreenY(rect.Y1, viewport, clippingArea);
-      int right = ToScreenX(rect.X2, viewport, clippingArea);
-      int top = ToScreenY(rect.Y2, viewport, clippingArea);
-      return new Rectangle(left, top, right - left , bottom - top );
-    }
-
-    /// <summary>
-    /// Transforms a 2d point in world coordinates to screen coordinates
-    /// </summary>
-    /// <param name="point">The point in world coordinates that should be transformed</param>
-    /// <param name="viewport">The target view port</param>
-    /// <param name="clippingArea">The target clipping area</param>
-    /// <returns>The point transformed to screen coordinates</returns>
-    public static Point ToScreen(PointD point, Rectangle viewport, RectangleD clippingArea) {
-      int x = ToScreenX(point.X, viewport, clippingArea);
-      int y = ToScreenY(point.Y, viewport, clippingArea);
-      return new Point(x, y);
-    }
-
-    /// <summary>
-    /// Transforms a point on the X-axis in world coordinates to screen coordinates
-    /// </summary>
-    /// <param name="x">The point on the X-axis in world coordinates that should be transformed</param>
-    /// <param name="viewport">The target view port</param>
-    /// <param name="clippingArea">The target clipping area</param>
-    /// <returns>The point transformed to screen coordinates</returns>
-    public static int ToScreenX(double x, Rectangle viewport, RectangleD clippingArea) {
-      return (int)(viewport.Left + viewport.Width/clippingArea.Width*(x - clippingArea.X1));
-    }
-
-    /// <summary>
-    /// Transforms a point on the Y-axis in world coordinates to screen coordinates
-    /// </summary>
-    /// <param name="y">The point on the Y-axis in world coordinates that should be transformed</param>
-    /// <param name="viewport">The target view port</param>
-    /// <param name="clippingArea">The target clipping area</param>
-    /// <returns>The point transformed to screen coordinates</returns>
-    public static int ToScreenY(double y, Rectangle viewport, RectangleD clippingArea) {
-      return (int)(viewport.Bottom - viewport.Height/clippingArea.Height*(y - clippingArea.Y1));
-    }
-  }
-}
Index: /trunk/sources/HeuristicLab.Visualization/3.2/Translate.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/Translate.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/Translate.cs	(revision 1964)
@@ -1,3 +1,4 @@
 using System.Drawing;
+using HeuristicLab.Visualization.Drawing;
 
 namespace HeuristicLab.Visualization {
Index: unk/sources/HeuristicLab.Visualization/3.2/WorldShape.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/WorldShape.cs	(revision 1963)
+++ 	(revision )
@@ -1,77 +1,0 @@
-﻿using System.Collections.Generic;
-using System.Drawing;
-using System.Drawing.Drawing2D;
-
-namespace HeuristicLab.Visualization {
-  /// <summary>
-  /// World shapes are composite shapes that have their own coordinate system
-  /// which is independent from their parent's coordinate system.
-  /// </summary>
-  public class WorldShape : IShape {
-    private RectangleD clippingArea; // own clipping area
-    private RectangleD boundingBox;
-    private IShape parent;
-
-    protected readonly List<IShape> shapes = new List<IShape>();
-
-    public WorldShape() {
-      this.clippingArea = new RectangleD(0, 0, 1, 1);
-      this.boundingBox = new RectangleD(0, 0, 1, 1);
-    }
-
-    public virtual void Draw(Graphics graphics) {
-      GraphicsState gstate = graphics.Save();
-
-      graphics.SetClip(Viewport);
-
-      foreach (IShape shape in shapes) {
-        // draw child shapes using our own clipping area
-        shape.Draw(graphics);
-      }
-
-      graphics.Restore(gstate);
-    }
-
-    public RectangleD BoundingBox {
-      get { return boundingBox; }
-      set { boundingBox = value; }
-    }
-
-    /// <summary>
-    /// The world shape's own clipping area.
-    /// This overrides the clipping area of the parent shape.
-    /// </summary>
-    public RectangleD ClippingArea {
-      get { return clippingArea; }
-      set { clippingArea = value; }
-    }
-
-    public Rectangle Viewport {
-      get {
-        // calculate our drawing area on the screen using our location and
-        // size in the parent (boundingBox), the parent's viewport and the
-        // parent's clipping area
-        Rectangle viewport = Transform.ToScreen(boundingBox, Parent.Viewport, Parent.ClippingArea);
-        return viewport;
-      }
-    }
-
-    public IShape Parent {
-      get { return parent; }
-      set { parent = value; }
-    }
-
-    public void ClearShapes() {
-      shapes.Clear();
-    }
-
-    public void AddShape(IShape shape) {
-      shape.Parent = this;
-      shapes.Add(shape);
-    }
-
-    public bool RemoveShape(IShape shape) {
-      return shapes.Remove(shape);
-    }
-  }
-}
Index: /trunk/sources/HeuristicLab.Visualization/3.2/XAxis.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/XAxis.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/XAxis.cs	(revision 1964)
@@ -1,3 +1,5 @@
+
 using System.Drawing;
+using HeuristicLab.Visualization.Drawing;
 using HeuristicLab.Visualization.LabelProvider;
 
Index: /trunk/sources/HeuristicLab.Visualization/3.2/XAxisGrid.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/XAxisGrid.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/XAxisGrid.cs	(revision 1964)
@@ -1,3 +1,4 @@
 using System.Drawing;
+using HeuristicLab.Visualization.Drawing;
 
 namespace HeuristicLab.Visualization {
Index: /trunk/sources/HeuristicLab.Visualization/3.2/YAxis.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/YAxis.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/YAxis.cs	(revision 1964)
@@ -1,4 +1,5 @@
 using System;
 using System.Drawing;
+using HeuristicLab.Visualization.Drawing;
 using HeuristicLab.Visualization.LabelProvider;
 using HeuristicLab.Visualization.Test;
Index: /trunk/sources/HeuristicLab.Visualization/3.2/YAxisGrid.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/3.2/YAxisGrid.cs	(revision 1963)
+++ /trunk/sources/HeuristicLab.Visualization/3.2/YAxisGrid.cs	(revision 1964)
@@ -1,3 +1,4 @@
 using System.Drawing;
+using HeuristicLab.Visualization.Drawing;
 
 namespace HeuristicLab.Visualization {
