diff --git a/mono/Assistance/Geometry.cs b/mono/Assistance/Geometry.cs
index 13bca52..749c039 100644
--- a/mono/Assistance/Geometry.cs
+++ b/mono/Assistance/Geometry.cs
@@ -114,7 +114,10 @@ namespace Assistance {
 			     + t1*( 3.0*ll - 2.0*l      );
         }
 
-		public static Track.Point interpolationSpline(Track.Point p0, Track.Point p1, Track.Point t0, Track.Point t1, double l) {
+		public static Point interpolationLinear(Point p0, Point p1, double l)
+			{ return p0*(1.0 - l) + p1*l; }
+
+		public static Point interpolationSpline(Point p0, Point p1, Point t0, Point t1, double l) {
 			double ll = l*l;
 			double lll = ll*l;
 			return p0*( 2.0*lll - 3.0*ll + 1.0)
@@ -123,7 +126,7 @@ namespace Assistance {
 			     + t1*(     lll - 1.0*ll      );
         }
 
-		public static Track.Point interpolationSplineTangent(Track.Point p0, Track.Point p1, Track.Point t0, Track.Point t1, double l) {
+		public static Point interpolationSplineTangent(Point p0, Point p1, Point t0, Point t1, double l) {
 			double ll = l*l;
 			return (p0 - p1)*6.0*(ll - l)
 			     + t0*( 3.0*ll - 4.0*l + 1.0)
diff --git a/mono/Assistance/Guideline.cs b/mono/Assistance/Guideline.cs
index b90545a..bc34af4 100644
--- a/mono/Assistance/Guideline.cs
+++ b/mono/Assistance/Guideline.cs
@@ -10,7 +10,7 @@ namespace Assistance {
 		public static readonly double snapScale = 1.0;
 		public static readonly double maxLenght = 20.0*snapLenght*snapScale;
 	
-		public virtual Track.WayPoint transformPoint(Track.WayPoint point)
+		public virtual Track.Point transformPoint(Track.Point point)
 			{ return point; }
 		
 		public virtual void draw(Cairo.Context context, bool active) { }
@@ -25,9 +25,9 @@ namespace Assistance {
 			double sumLength = 0.0;
 			double sumDeviation = 0.0;
 			
-			Point prev = track.points[0].point.position;
-			foreach(Track.WayPoint wp in track.points) {
-				Point p = wp.point.position;
+			Point prev = track.points[0].position;
+			foreach(Track.Point tp in track.points) {
+				Point p = tp.position;
 				double length = (p - prev).len();
 				sumLength += length;
 				
@@ -36,8 +36,8 @@ namespace Assistance {
 					double weight = length*Geometry.logNormalDistribuitionUnscaled(midStepLength, snapLenght, snapScale);
 					sumWeight += weight;
 				
-					Track.WayPoint nwp = transformPoint(wp);
-					double deviation = (nwp.point.position - p).len();
+					Track.Point ntp = transformPoint(tp);
+					double deviation = (ntp.position - p).len();
 					sumDeviation += weight*deviation;
 				}
 				prev = p;
diff --git a/mono/Assistance/GuidelineLine.cs b/mono/Assistance/GuidelineLine.cs
index 77c993d..ed7cbfc 100644
--- a/mono/Assistance/GuidelineLine.cs
+++ b/mono/Assistance/GuidelineLine.cs
@@ -26,10 +26,9 @@ namespace Assistance {
 			context.Restore();
 		}
 		
-		public override Track.WayPoint transformPoint(Track.WayPoint p) {
-			Track.WayPoint np = p;
-			np.point.position = Point.dot(p.point.position - p0, direction)*direction + p0;
-			np.tangent.position = direction;
+		public override Track.Point transformPoint(Track.Point p) {
+			Track.Point np = p;
+			np.position = Point.dot(p.position - p0, direction)*direction + p0;
 			return np;
 		}
 	}
diff --git a/mono/Assistance/InputManager.cs b/mono/Assistance/InputManager.cs
index 02ebce9..1c595ac 100644
--- a/mono/Assistance/InputManager.cs
+++ b/mono/Assistance/InputManager.cs
@@ -270,32 +270,35 @@ namespace Assistance {
 			return createTrack(b, device, touchId, ticks);
 		}
 		
-		private void addTrackPoint(Track track, Track.Point point, double time, bool final) {
+		private void addTrackPoint(Track track, Point position, double pressure, Point tilt, double time, bool final) {
 			// fix time
 			if (track.points.Count > 0)
 				time = Math.Max(time, track.getLast().time + Timer.step);
 			
 			// calc length
 			double length = track.points.Count > 0
-			              ? (point.position - track.getLast().point.position).len() + track.getLast().length
+			              ? (position - track.getLast().position).len() + track.getLast().length
 			              : 0.0;
 			
 			// add
-			track.points.Add( new Track.WayPoint(
-				point,
-				new Track.Point(),
+			track.points.Add( new Track.Point(
+				position,
+				pressure,
+				tilt,
 				(double)track.points.Count,
 				time,
-				length,
-				track.points.Count,
+				length,				
 				final ));
 			++track.wayPointsAdded;
 		}
 		
 		private void touchTracks(bool finish = false) {
-			foreach(Track track in tracks[0])
-				if (!track.isFinished() && track.points.Count > 0)
-					addTrackPoint(track, track.getLast().point, track.getLast().time, finish);
+			foreach(Track track in tracks[0]) {
+				if (!track.isFinished() && track.points.Count > 0) {
+					Track.Point p = track.getLast();
+					addTrackPoint(track, p.position, p.pressure, p.tilt, p.time, finish);
+				}
+			}
 			paintTracks();
 		}
 		
@@ -331,12 +334,12 @@ namespace Assistance {
 			{ return tracks[modifiers.Count]; }
 		
 		
-		public void trackEvent(Gdk.Device device, long touchId, Track.Point point, bool final, long ticks) {
+		public void trackEvent(Gdk.Device device, long touchId, Point position, double pressure, Point tilt, bool final, long ticks) {
 			if (isActive()) {
 				Track track = getTrack(device, touchId, ticks);
 				if (!track.isFinished()) {
 					double time = (double)(ticks - track.keyHistory.ticks)*Timer.step - track.keyHistory.timeOffset;
-					addTrackPoint(track, point, time, final);
+					addTrackPoint(track, position, pressure, tilt, time, final);
 					paintTracks();
 				}
 			}
@@ -433,16 +436,16 @@ namespace Assistance {
 						int level = keyPointsSent;
 						
 						color.apply(context);
-						context.MoveTo(track.points[start].point.position.x, track.points[start].point.position.y);
+						context.MoveTo(track.points[start].position.x, track.points[start].position.y);
 						for(int i = start + 1; i < track.points.Count; ++i) {
 							while(level < handler.keys.Count && handler.keys[level] <= i) {
 								context.Stroke();
-								context.MoveTo(track.points[i-1].point.position.x, track.points[i-1].point.position.y);
+								context.MoveTo(track.points[i-1].position.x, track.points[i-1].position.y);
 								color.a *= levelAlpha;
 								color.apply(context);
 								++level;
 							}
-							context.LineTo(track.points[i].point.position.x, track.points[i].point.position.y);
+							context.LineTo(track.points[i].position.x, track.points[i].position.y);
 						}
 					}
 				}
diff --git a/mono/Assistance/InputModifierAssistants.cs b/mono/Assistance/InputModifierAssistants.cs
index 3a98ba1..c7273c6 100644
--- a/mono/Assistance/InputModifierAssistants.cs
+++ b/mono/Assistance/InputModifierAssistants.cs
@@ -20,8 +20,8 @@ namespace Assistance {
 			public InputManager.KeyPoint.Holder holder = null;
 			public List<Guideline> guidelines = new List<Guideline>();
 			
-			public override Track.WayPoint calcWayPoint(double originalIndex) {
-				Track.WayPoint p = base.calcWayPoint(originalIndex);
+			public override Track.Point calcPoint(double originalIndex) {
+				Track.Point p = base.calcPoint(originalIndex);
 				return guidelines.Count > 0 ? guidelines[0].transformPoint(p) : p;
 			}
 		}
@@ -36,7 +36,7 @@ namespace Assistance {
 
 				Track.Handler handler = new Track.Handler(this, track);
 				modifier = new Modifier(handler);
-				workarea.getGuidelines(modifier.guidelines, track.points[0].point.position);
+				workarea.getGuidelines(modifier.guidelines, track.points[0].position);
 				if (defaultTangents && modifier.guidelines.Count == 0)
 					{ base.modify(track, keyPoint, outTracks); return; }
 				
@@ -89,7 +89,7 @@ namespace Assistance {
 			
 			// add points
 			for(int i = start; i < track.points.Count; ++i)
-				subTrack.points.Add(modifier.calcWayPoint(i));
+				subTrack.points.Add(modifier.calcPoint(i));
 			subTrack.wayPointsAdded = subTrack.points.Count - start;
 			
 			track.wayPointsRemoved = 0;
@@ -107,7 +107,7 @@ namespace Assistance {
 			if (track.handler == null) return;
 			Track subTrack = track.handler.tracks[0];
 			if (subTrack.points.Count > 0)
-				drawHover(context, subTrack.getLast().point.position);
+				drawHover(context, subTrack.getLast().position);
 		}
 	}
 }
diff --git a/mono/Assistance/InputModifierInterpolation.cs b/mono/Assistance/InputModifierInterpolation.cs
index b6af59b..da499c1 100644
--- a/mono/Assistance/InputModifierInterpolation.cs
+++ b/mono/Assistance/InputModifierInterpolation.cs
@@ -13,10 +13,10 @@ namespace Assistance {
 			this.precisionSqr = this.precision*this.precision;
 		}
 	
-		public void addSegment(Track track, Track.WayPoint p0, Track.WayPoint p1, int level = 0) {
-			if (level >= maxRecursion || (p1.point.position - p0.point.position).lenSqr() <= precisionSqr)
+		public void addSegment(Track track, Track.Point p0, Track.Point p1, int level = 0) {
+			if (level >= maxRecursion || (p1.position - p0.position).lenSqr() <= precisionSqr)
 				{ track.points.Add(p1); return; }
-			Track.WayPoint p = track.modifier.calcWayPoint(0.5*(p0.originalIndex + p1.originalIndex));
+			Track.Point p = track.modifier.calcPoint(0.5*(p0.originalIndex + p1.originalIndex));
 			addSegment(track, p0, p, level + 1);
 			addSegment(track, p, p1, level + 1);
 		}
@@ -49,9 +49,9 @@ namespace Assistance {
 			}
 			
 			// add points
-			Track.WayPoint p0 = subTrack.modifier.calcWayPoint(start - 1);
+			Track.Point p0 = subTrack.modifier.calcPoint(start - 1);
 			for(int i = start; i < track.points.Count; ++i) {
-				Track.WayPoint p1 = subTrack.modifier.calcWayPoint(i);
+				Track.Point p1 = subTrack.modifier.calcPoint(i);
 				addSegment(subTrack, p0, p1);
 				p0 = p1;
 			}
diff --git a/mono/Assistance/InputModifierTangents.cs b/mono/Assistance/InputModifierTangents.cs
index 82f30ae..1846650 100644
--- a/mono/Assistance/InputModifierTangents.cs
+++ b/mono/Assistance/InputModifierTangents.cs
@@ -3,27 +3,57 @@ using System.Collections.Generic;
 
 namespace Assistance {
 	public class InputModifierTangents: InputManager.Modifier {
+		public struct Tangent {
+			public Point position;
+			public double pressure;
+			public Point tilt;
+			
+			public Tangent(
+				Point position,
+				double pressure = 0.0,
+				Point tilt = new Point() )
+			{
+				this.position = position;
+				this.pressure = pressure;
+				this.tilt = tilt;
+			}
+		}
+	
 		public class Modifier: Track.Modifier {
 			public Modifier(Track.Handler handler):
 				base(handler) { }
 			
 			public InputManager.KeyPoint.Holder holder = null;
-			public readonly List<Track.Point> tangents = new List<Track.Point>();
+			public readonly List<Tangent> tangents = new List<Tangent>();
 			
-			public override Track.WayPoint calcWayPoint(double originalIndex) {
+			public override Track.Point calcPoint(double originalIndex) {
 				double frac;
 				int i0 = original.floorIndex(originalIndex, out frac);
 				int i1 = original.ceilIndex(originalIndex);
-				Track.WayPoint p0 = original.getWayPoint(i0);
-				Track.WayPoint p1 = original.getWayPoint(i1);
-				p0.tangent = tangents[i0];
-				p1.tangent = tangents[i1];
-				Track.WayPoint p = Track.interpolate(p0, p1, frac);
+				Track.Point p = i0 < 0 ? new Track.Point()
+				              : interpolateSpline(
+									original.points[i0],
+									original.points[i1],
+									tangents[i0],
+									tangents[i1],
+									frac );
 				p.originalIndex = originalIndex;
 				return p;
 			}
 		}
 
+		public static Track.Point interpolateSpline(Track.Point p0, Track.Point p1, Tangent t0, Tangent t1, double l) {
+			if (l <= Geometry.precision) return p0;
+			if (l >= 1.0 - Geometry.precision) return p1;
+			return new Track.Point(
+				Geometry.interpolationSpline(p0.position, p1.position, t0.position, t1.position, l),
+				Geometry.interpolationSpline(p0.pressure, p1.pressure, t0.pressure, t1.pressure, l),
+				Geometry.interpolationSpline(p0.tilt, p1.tilt, t0.tilt, t1.tilt, l),
+				Geometry.interpolationLinear(p0.originalIndex, p1.originalIndex, l),
+				Geometry.interpolationLinear(p0.time, p1.time, l),
+				Geometry.interpolationLinear(p0.length, p1.length, l) );
+		}
+
 		public override void modify(Track track, InputManager.KeyPoint keyPoint, List<Track> outTracks) {
 			if (track.handler == null) {
 				track.handler = new Track.Handler(this, track);
@@ -41,7 +71,7 @@ namespace Assistance {
 			
 			if (!track.isChanged && subTrack.points.Count == track.points.Count - 1) {
 				// add temporary point
-				modifier.tangents.Add(new Track.Point());
+				modifier.tangents.Add(new Tangent());
 				subTrack.points.Add(track.getLast());
 				++subTrack.wayPointsAdded;
 			} else {
@@ -61,7 +91,7 @@ namespace Assistance {
 				// add first point
 				int index = start;
 				if (index == 0) {
-					modifier.tangents.Add(new Track.Point());
+					modifier.tangents.Add(new Tangent());
 					subTrack.points.Add(track.getLast());
 					++index;
 				}
@@ -69,15 +99,17 @@ namespace Assistance {
 				// add points with tangents
 				if (track.points.Count > 2) {
 					while(index < track.points.Count - 1) {
-						Track.WayPoint p = track.points[index];
-						double t0 = track.points[index-1].time;
-						double t2 = track.points[index+1].time;
-						double dt = t2 - t0;
-						p.tangent = dt > Geometry.precision
-						          ? (track.points[index+1].point - track.points[index-1].point)*(p.time - t0)/dt
-						          : new Track.Point();
-						modifier.tangents.Add(p.tangent);
-						subTrack.points.Add(p);
+						Track.Point p0 = track.points[index-1];
+						Track.Point p1 = track.points[index];
+						Track.Point p2 = track.points[index+1];
+						double dt = p2.time - p0.time;
+						double k = dt > Geometry.precision ? (p1.time - p0.time)/dt : 0.0;
+						Tangent tangent = new Tangent(
+							(p2.position - p0.position)*k,
+							(p2.pressure - p0.pressure)*k,
+							(p2.tilt - p0.tilt)*k );
+						modifier.tangents.Add(tangent);
+						subTrack.points.Add(p1);
 						++index;
 					}
 				}
@@ -94,7 +126,7 @@ namespace Assistance {
 				
 				if (track.isFinished()) {
 					// finish
-					modifier.tangents.Add(new Track.Point());
+					modifier.tangents.Add(new Tangent());
 					subTrack.points.Add(track.getLast());
 					++subTrack.wayPointsAdded;
 				} else {
diff --git a/mono/Assistance/MainWindow.cs b/mono/Assistance/MainWindow.cs
index 6e66fd5..138d843 100644
--- a/mono/Assistance/MainWindow.cs
+++ b/mono/Assistance/MainWindow.cs
@@ -148,16 +148,9 @@ namespace Assistance {
 		}
 		
 		void addTrackPoint(Gdk.Device device, Point p, double time, double pressure, Point tilt, bool final) {
-			if (!painting)
-				return;
-
-			Track.Point point = new Track.Point();
-			point.position = p;
-			point.pressure = pressure;
-			point.tilt = tilt;	
-			
+			if (!painting) return;
 			long ticks = ticksStart + (long)Math.Round((time - timeStart)*Timer.frequency);
-			workarea.inputManager.trackEvent(device, touchId, point, final, ticks);
+			workarea.inputManager.trackEvent(device, touchId, p, pressure, tilt, final, ticks);
 		}
 
 		void addTrackPoint(double x, double y, uint t, Gdk.Device device, double[] axes, bool final) {
diff --git a/mono/Assistance/ModifierSnowflake.cs b/mono/Assistance/ModifierSnowflake.cs
index 598da76..76fbd58 100644
--- a/mono/Assistance/ModifierSnowflake.cs
+++ b/mono/Assistance/ModifierSnowflake.cs
@@ -19,11 +19,10 @@ namespace Assistance {
 			public InputManager.KeyPoint.Holder holder = null;
 			public List<Guideline> guidelines = new List<Guideline>();
 			
-			public override Track.WayPoint calcWayPoint(double originalIndex) {
-				Track.WayPoint p = base.calcWayPoint(originalIndex);
-				Point pp = p.point.position - center;
-				p.point.position = center + new Point(Point.dot(pp, px), Point.dot(pp, py));
-				p.tangent.position = new Point(Point.dot(p.tangent.position, px), Point.dot(p.tangent.position, py));
+			public override Track.Point calcPoint(double originalIndex) {
+				Track.Point p = base.calcPoint(originalIndex);
+				Point pp = p.position - center;
+				p.position = center + new Point(Point.dot(pp, px), Point.dot(pp, py));
 				return p;
 			}
 		}
@@ -78,7 +77,7 @@ namespace Assistance {
 				
 				// add points
 				for(int i = start; i < track.points.Count; ++i)
-					subTrack.points.Add( subTrack.modifier.calcWayPoint(i) );
+					subTrack.points.Add( subTrack.modifier.calcPoint(i) );
 				subTrack.wayPointsAdded += subTrack.points.Count - start;
 			}
 			
diff --git a/mono/Assistance/ModifierSpiro.cs b/mono/Assistance/ModifierSpiro.cs
index f1d31ba..6391e56 100644
--- a/mono/Assistance/ModifierSpiro.cs
+++ b/mono/Assistance/ModifierSpiro.cs
@@ -14,44 +14,27 @@ namespace Assistance {
 		public class Modifier: Track.Modifier {
 			public double angle;
 			public double radius;
+			public double speed;
 		
-			public Modifier(Track.Handler handler, double angle, double radius):
-				base(handler) { this.angle = angle; this.radius = radius; }
-			public override Track.WayPoint calcWayPoint(double originalIndex) {
-				Track.WayPoint p = base.calcWayPoint(originalIndex);
+			public Modifier(Track.Handler handler, double angle, double radius, double speed = 1.0):
+				base(handler) { this.angle = angle; this.radius = radius; this.speed = speed; }
+
+			public override Track.Point calcPoint(double originalIndex) {
+				Track.Point p = base.calcPoint(originalIndex);
 				
+				double frac;
+				int i0 = original.floorIndex(originalIndex, out frac);
+				int i1 = original.ceilIndex(originalIndex);
+				if (i0 < 0) return p;
+
 				Handler handler = (Handler)this.handler;
-				double frac, a0, a1;
-				Point p0, p1;
-				int i = original.floorIndex(originalIndex, out frac);
-				if (frac > Geometry.precision) {
-					a0 = handler.angles[i];
-					a1 = handler.angles[i+1];
-					p0 = original.points[i].point.position;
-					p1 = original.points[i+1].point.position;
-				} else
-				if (i > 0) {
-					a0 = handler.angles[i-1];
-					a1 = handler.angles[i];
-					p0 = original.points[i-1].point.position;
-					p1 = original.points[i].point.position;
-					frac = 1.0;
-				} else {
-					a0 = handler.angles[i];
-					a1 = handler.angles[i];
-					p0 = original.points[i].point.position;
-					p1 = original.points[i].point.position;
-				}
-				
-				double angle = Geometry.interpolationLinear(a0, a1, frac) + this.angle;
-				double da = a1 - a0;
-				
-				double radius = 2.0*this.radius*p.point.pressure;
+				double angle = this.angle + speed*Geometry.interpolationLinear(
+					handler.angles[i0], handler.angles[i1], frac);
+				double radius = 2.0*this.radius*p.pressure;
 				double s = Math.Sin(angle);
 				double c = Math.Cos(angle);
 			
-				p.point.position += new Point(c, s)*radius;
-				p.tangent.position = ((p1 - p0) + new Point(-s, c)*radius*(a1 - a0)).normalize();
+				p.position += new Point(c, s)*radius;
 				return p;
 			}
 		}
@@ -91,8 +74,8 @@ namespace Assistance {
 			for(int i = start; i < track.points.Count; ++i) {
 				if (i > 0) {
 					double dl = track.points[i].length - track.points[i-1].length;
-					double da = track.points[i].point.pressure > Geometry.precision
-					          ? 0.25*dl/(2.0*radius*track.points[i].point.pressure) : 0.0;
+					double da = track.points[i].pressure > Geometry.precision
+					          ? 0.25*dl/(2.0*radius*track.points[i].pressure) : 0.0;
 					handler.angles.Add(handler.angles[i-1] + da);
 				} else {
 					handler.angles.Add(0.0);
@@ -121,10 +104,10 @@ namespace Assistance {
 							double step = segmentSize/Math.Abs(nextAngle - prevAngle);
 							double end = 1.0 - 0.5*step;
 							for(double frac = step; frac < end; frac += step)
-								subTrack.points.Add( subTrack.modifier.calcWayPoint((double)i - 1.0 + frac) );
+								subTrack.points.Add( subTrack.modifier.calcPoint((double)i - 1.0 + frac) );
 						}
 					}
-					subTrack.points.Add( subTrack.modifier.calcWayPoint(i) );
+					subTrack.points.Add( subTrack.modifier.calcPoint(i) );
 				}
 				subTrack.wayPointsAdded += subTrack.points.Count - subStart;
 			}
diff --git a/mono/Assistance/ToolFull.cs b/mono/Assistance/ToolFull.cs
index 391e9fb..0ca178f 100644
--- a/mono/Assistance/ToolFull.cs
+++ b/mono/Assistance/ToolFull.cs
@@ -25,15 +25,14 @@ namespace Assistance {
 			return true;
 		}
 
-		private void paintPoint(DynamicSurface surface, Track.WayPoint point) {
-			Point p = point.point.position;
-			double r = pen.width*point.point.pressure;
+		private void paintPoint(DynamicSurface surface, Track.Point point) {
+			Point p = point.position;
+			double r = pen.width*point.pressure;
 			Drawing.Color color = pen.color;
 			if (r < 0.01) r = 0.01;
 			if (r > Geometry.precision && r < 0.5)
 				{ color.a *= r/0.5; r = 0.5; }
 			double rr = r + 1.0;
-			//rr += 10.0*(Math.Abs(point.tangent.position.x) + Math.Abs(point.tangent.position.y))
 			
 			surface.expand(new Rectangle(p.x - rr, p.y - rr, p.x + rr, p.y + rr));
 
@@ -43,14 +42,6 @@ namespace Assistance {
 			surface.context.Arc(p.x, p.y, r, 0.0, 2.0*Math.PI);
 			surface.context.Fill();
 
-			//pen.apply(surface.context);
-			//color.a = 0.5;
-			//color.apply(surface.context);
-			//surface.context.LineWidth = 0.5;
-			//surface.context.MoveTo(p.x, p.y);
-			//surface.context.RelLineTo(-10.0*point.tangent.position.y, 10.0*point.tangent.position.x);
-			//surface.context.Stroke();
-
 			surface.context.Restore();
 		}
 
diff --git a/mono/Assistance/Track.cs b/mono/Assistance/Track.cs
index 75d81f7..fdff864 100644
--- a/mono/Assistance/Track.cs
+++ b/mono/Assistance/Track.cs
@@ -26,8 +26,8 @@ namespace Assistance {
 				{ get { return handler.owner; } }
 			public Track original
 				{ get { return handler.original; } }
-			public virtual WayPoint calcWayPoint(double originalIndex) {
-				WayPoint p = original.calcWayPoint(originalIndex);
+			public virtual Point calcPoint(double originalIndex) {
+				Point p = original.calcPoint(originalIndex);
 				p.originalIndex = originalIndex;
 				return p;
 			}
@@ -37,66 +37,28 @@ namespace Assistance {
 			public Assistance.Point position;
 			public double pressure;
 			public Assistance.Point tilt;
-	
-			public Point(
-				Assistance.Point position,
-				double pressure,
-				Assistance.Point tilt
-			) {
-				this.position = position;
-				this.pressure = pressure;
-				this.tilt = tilt;
-			}
-			
-			public static Point operator+ (Point a, Point b)
-				{ return new Point(a.position + b.position, a.pressure + b.pressure, a.tilt + b.tilt); }
-			public static Point operator- (Point a, Point b)
-				{ return new Point(a.position - b.position, a.pressure - b.pressure, a.tilt - b.tilt); }
-			public static Point operator* (Point a, double b)
-				{ return new Point(a.position*b, a.pressure*b, a.tilt*b); }
-			public static Point operator* (double a, Point b)
-				{ return a*b; }
-			public static Point operator/ (Point a, double b)
-				{ return a*(1.0/b); }
-	
-			public bool isEqual(Point other) {
-				return position.isEqual(other.position)
-					&& Geometry.isEqual(pressure, other.pressure)
-					&& tilt.isEqual(other.tilt);
-			}
-	
-			public Point normalize() {
-				double l = position.len();
-				return l > Geometry.precision ? this/l : this;
-			}
-		}
-
-		public struct WayPoint {
-			public Point point;
-			public Point tangent;
 
 			public double originalIndex;
 			public double time;
 			public double length;
 			
-			public int depRootIndex;
 			public bool final;
 	
-			public WayPoint(
-				Point point,
-				Point tangent = new Point(),
+			public Point(
+				Assistance.Point position,
+				double pressure = 0.5,
+				Assistance.Point tilt = new Assistance.Point(),
 				double originalIndex = 0.0,
 				double time = 0.0,
 				double length = 0.0,
-				int depRootIndex = 0,
 				bool final = false
 			) {
-				this.point = point;
-				this.tangent = tangent;
+				this.position = position;
+				this.pressure = pressure;
+				this.tilt = tilt;
 				this.originalIndex = originalIndex;
 				this.time = time;
 				this.length = length;
-				this.depRootIndex = depRootIndex;
 				this.final = final;
 			}
 		}
@@ -107,7 +69,7 @@ namespace Assistance {
 		public readonly long id;
 		public readonly Gdk.Device device;
 		public readonly long touchId;
-		public readonly List<WayPoint> points = new List<WayPoint>();
+		public readonly List<Point> points = new List<Point>();
 		public readonly KeyHistory<Gdk.Key>.Holder keyHistory;
 		public readonly KeyHistory<uint>.Holder buttonHistory;
 
@@ -152,10 +114,10 @@ namespace Assistance {
 		public int getLevel()
 			{ return original == null ? 0 : original.getLevel() + 1; }
 		
-		public WayPoint getFirst()
-			{ return getWayPoint(0); }
-		public WayPoint getLast()
-			{ return getWayPoint(points.Count - 1); }
+		public Point getFirst()
+			{ return getPoint(0); }
+		public Point getLast()
+			{ return getPoint(points.Count - 1); }
 		public bool isFinished()
 			{ return points.Count > 0 && getLast().final; }
 		
@@ -179,19 +141,19 @@ namespace Assistance {
 		public int ceilIndex(double index)
 			{ return clampIndex(ceilIndexNoClamp(index)); }
 		
-		public WayPoint getWayPoint(int index) {
+		public Point getPoint(int index) {
 			index = clampIndex(index);
-			return index < 0 ? new WayPoint() : points[index];
+			return index < 0 ? new Point() : points[index];
 		}
-		public WayPoint floorWayPoint(double index, out double frac)
-			{ return getWayPoint(floorIndex(index, out frac)); }
-		public WayPoint floorWayPoint(double index)
-			{ return getWayPoint(floorIndex(index)); }
-		public WayPoint ceilWayPoint(double index)
-			{ return getWayPoint(ceilIndex(index)); }
+		public Point floorPoint(double index, out double frac)
+			{ return getPoint(floorIndex(index, out frac)); }
+		public Point floorPoint(double index)
+			{ return getPoint(floorIndex(index)); }
+		public Point ceilPoint(double index)
+			{ return getPoint(ceilIndex(index)); }
 		
-		private delegate double WayPointFieldGetter(WayPoint p);
-		private double binarySearch(double value, WayPointFieldGetter getter) {
+		private delegate double PointFieldGetter(Point p);
+		private double binarySearch(double value, PointFieldGetter getter) {
 			// points[a].value <= value < points[b].value
 			
 			if (points.Count <= 0) return 0.0;
@@ -215,59 +177,59 @@ namespace Assistance {
 		}
 			
 		public double indexByOriginalIndex(double originalIndex)
-			{ return binarySearch(originalIndex, delegate(WayPoint p) { return p.originalIndex; }); }
+			{ return binarySearch(originalIndex, delegate(Point p) { return p.originalIndex; }); }
 		public double indexByTime(double time)
-			{ return binarySearch(time, delegate(WayPoint p) { return p.time; }); }
+			{ return binarySearch(time, delegate(Point p) { return p.time; }); }
 		public double indexByLength(double length)
-			{ return binarySearch(length, delegate(WayPoint p) { return p.length; }); }
+			{ return binarySearch(length, delegate(Point p) { return p.length; }); }
 		
 		public double originalIndexByIndex(double index) {
 			double frac;
-			WayPoint p0 = floorWayPoint(index, out frac), p1 = ceilWayPoint(index);
+			Point p0 = floorPoint(index, out frac), p1 = ceilPoint(index);
 			return Geometry.interpolationLinear(p0.originalIndex, p1.originalIndex, frac);
 		}
 		public double timeByIndex(double index) {
 			double frac;
-			WayPoint p0 = floorWayPoint(index, out frac), p1 = ceilWayPoint(index);
+			Point p0 = floorPoint(index, out frac), p1 = ceilPoint(index);
 			return Geometry.interpolationLinear(p0.time, p1.time, frac);
 		}
 		public double lengthByIndex(double index) {
 			double frac;
-			WayPoint p0 = floorWayPoint(index, out frac), p1 = ceilWayPoint(index);
+			Point p0 = floorPoint(index, out frac), p1 = ceilPoint(index);
 			return Geometry.interpolationLinear(p0.length, p1.length, frac);
 		}
 
-		public WayPoint calcWayPoint(double index) {
+		public Point calcPoint(double index) {
 			return modifier == null
-			     ? interpolate(index)
-			     : modifier.calcWayPoint( originalIndexByIndex(index) );
+			     ? interpolateLinear(index)
+			     : modifier.calcPoint( originalIndexByIndex(index) );
 		}
 		
-		public WayPoint interpolate(double index) {
+		public Point interpolateLinear(double index) {
 			double frac;
-			WayPoint p0 = floorWayPoint(index, out frac);
-			WayPoint p1 = ceilWayPoint(index);
-			return interpolate(p0, p1, frac);
+			Point p0 = floorPoint(index, out frac);
+			Point p1 = ceilPoint(index);
+			return interpolateLinear(p0, p1, frac);
 		}
 
-		public static WayPoint interpolate(WayPoint p0, WayPoint p1, double l) {
+		public static Point interpolateLinear(Point p0, Point p1, double l) {
 			if (l <= Geometry.precision) return p0;
 			if (l >= 1.0 - Geometry.precision) return p1;
-			return new WayPoint(
-				Geometry.interpolationSpline(p0.point, p1.point, p0.tangent, p1.tangent, l),
-				Geometry.interpolationSplineTangent(p0.point, p1.point, p0.tangent, p1.tangent, l),
+			return new Point(
+				Geometry.interpolationLinear(p0.position, p1.position, l),
+				Geometry.interpolationLinear(p0.pressure, p1.pressure, l),
+				Geometry.interpolationLinear(p0.tilt, p1.tilt, l),
 				Geometry.interpolationLinear(p0.originalIndex, p1.originalIndex, l),
 				Geometry.interpolationLinear(p0.time, p1.time, l),
-				Geometry.interpolationLinear(p0.length, p1.length, l),
-				p1.depRootIndex );
+				Geometry.interpolationLinear(p0.length, p1.length, l) );
 		}
 		
 		public void print() {
-			foreach(WayPoint wp in points)
+			foreach(Point wp in points)
 				Console.Write(
 					"{2:f1}, ",
-					wp.point.position.x,
-					wp.point.position.y,
+					wp.position.x,
+					wp.position.y,
 					wp.originalIndex );
 			Console.WriteLine();
 		}