|
|
cfceb0 |
using System;
|
|
|
cfceb0 |
using System.Collections.Generic;
|
|
|
b82ef4 |
using Assistance.Drawing;
|
|
|
cfceb0 |
|
|
|
cfceb0 |
namespace Assistance {
|
|
|
cfceb0 |
public class Track {
|
|
|
b82ef4 |
public static readonly Pen pen = new Pen("Dark Green", 3.0);
|
|
|
c66393 |
public static readonly Pen penSpecial = new Pen("Blue", 3.0);
|
|
|
b82ef4 |
public static readonly Pen penPreview = new Pen("Dark Green", 1.0, 0.25);
|
|
|
77e178 |
|
|
|
77e178 |
private static long lastTouchId;
|
|
|
77e178 |
|
|
|
77e178 |
public long touchId;
|
|
|
c66393 |
public readonly Gdk.Device device;
|
|
|
b82ef4 |
public readonly List<trackpoint> points = new List<trackpoint>();</trackpoint></trackpoint>
|
|
|
cfceb0 |
|
|
|
77c1c7 |
private readonly List<track> parents = new List<track>();
|
|
|
77c1c7 |
private readonly List<geometry.transformfunc> transformFuncs = new List<geometry.transformfunc>();</geometry.transformfunc></geometry.transformfunc>
|
|
|
77c1c7 |
|
|
|
77e178 |
public static long getTouchId() { return ++lastTouchId; }
|
|
|
77e178 |
|
|
|
77e178 |
public Track(long touchId, Gdk.Device device)
|
|
|
c66393 |
{
|
|
|
77e178 |
this.touchId = touchId;
|
|
|
c66393 |
this.device = device;
|
|
|
c66393 |
}
|
|
|
77c1c7 |
|
|
|
77c1c7 |
public Track(Track parent, Geometry.TransformFunc transformFunc):
|
|
|
77e178 |
this(parent.touchId, parent.device)
|
|
|
77c1c7 |
{
|
|
|
77c1c7 |
parents.AddRange(parent.parents);
|
|
|
77c1c7 |
parents.Add(parent);
|
|
|
77c1c7 |
transformFuncs.AddRange(parent.transformFuncs);
|
|
|
77c1c7 |
transformFuncs.Add(transformFunc);
|
|
|
77c1c7 |
}
|
|
|
77c1c7 |
|
|
|
77c1c7 |
public Track(Track parent, Geometry.TransformFunc transformFunc, double precision):
|
|
|
77c1c7 |
this(parent, transformFunc)
|
|
|
77c1c7 |
{
|
|
|
77c1c7 |
rebuild(precision);
|
|
|
77c1c7 |
}
|
|
|
77c1c7 |
|
|
|
72b17c |
public Track createChild(Geometry.TransformFunc transformFunc){
|
|
|
77c1c7 |
return new Track(this, transformFunc);
|
|
|
77c1c7 |
}
|
|
|
77c1c7 |
|
|
|
77c1c7 |
public Track createChildAndBuild(Geometry.TransformFunc transformFunc, double precision = 1.0) {
|
|
|
77c1c7 |
return new Track(this, transformFunc, precision);
|
|
|
77c1c7 |
}
|
|
|
c66393 |
|
|
|
cfceb0 |
public Rectangle getBounds() {
|
|
|
cfceb0 |
if (points.Count == 0)
|
|
|
cfceb0 |
return new Rectangle();
|
|
|
b82ef4 |
Rectangle bounds = new Rectangle(points[0].point);
|
|
|
b82ef4 |
foreach(TrackPoint p in points)
|
|
|
b82ef4 |
bounds = bounds.expand(p.point);
|
|
|
b82ef4 |
return bounds.inflate(Math.Max(pen.width, penPreview.width) + 2.0);
|
|
|
cfceb0 |
}
|
|
|
72b17c |
|
|
|
b82ef4 |
public TrackPoint transform(TrackPoint p) {
|
|
|
b82ef4 |
p.point = Geometry.transform(transformFuncs, p.point);
|
|
|
b82ef4 |
return p;
|
|
|
72b17c |
}
|
|
|
72b17c |
|
|
|
b82ef4 |
private void addSpline(
|
|
|
b82ef4 |
TrackPoint p0, TrackPoint p1,
|
|
|
b82ef4 |
TrackPoint t0, TrackPoint t1,
|
|
|
b82ef4 |
TrackPoint tp0, TrackPoint tp1,
|
|
|
b82ef4 |
double l0, double l1,
|
|
|
b82ef4 |
double precisionSqr
|
|
|
b82ef4 |
) {
|
|
|
b82ef4 |
if ((tp1.point - tp0.point).lenSqr() < precisionSqr) {
|
|
|
77c1c7 |
points.Add(tp1);
|
|
|
77c1c7 |
} else {
|
|
|
77c1c7 |
double l = 0.5*(l0 + l1);
|
|
|
c66393 |
TrackPoint p = p0.spawn(
|
|
|
b82ef4 |
Geometry.splinePoint(p0.point, p1.point, t0.point, t1.point, l),
|
|
|
b82ef4 |
p0.time + l*(p1.time - p0.time),
|
|
|
b82ef4 |
Geometry.splinePoint(p0.pressure, p1.pressure, t0.pressure, t1.pressure, l),
|
|
|
b82ef4 |
Geometry.splinePoint(p0.tilt, p1.tilt, t0.tilt, t1.tilt, l) );
|
|
|
b82ef4 |
TrackPoint tp = transform(p);
|
|
|
77c1c7 |
addSpline(p0, p1, t0, t1, tp0, tp, l0, l, precisionSqr);
|
|
|
77c1c7 |
addSpline(p0, p1, t0, t1, tp, tp1, l, l1, precisionSqr);
|
|
|
77c1c7 |
}
|
|
|
77c1c7 |
}
|
|
|
77c1c7 |
|
|
|
77c1c7 |
public void rebuild(double precision = 1.0) {
|
|
|
77c1c7 |
if (parents.Count == 0) return;
|
|
|
77c1c7 |
|
|
|
77c1c7 |
points.Clear();
|
|
|
77c1c7 |
|
|
|
77c1c7 |
Track root = parents[0];
|
|
|
77c1c7 |
if (root.points.Count < 2) {
|
|
|
b82ef4 |
foreach(TrackPoint p in root.points)
|
|
|
b82ef4 |
points.Add( transform(p) );
|
|
|
77c1c7 |
return;
|
|
|
77c1c7 |
}
|
|
|
77c1c7 |
|
|
|
77c1c7 |
double precisionSqr = precision * precision;
|
|
|
b82ef4 |
TrackPoint p0 = root.points[0];
|
|
|
b82ef4 |
TrackPoint p1 = root.points[1];
|
|
|
b82ef4 |
TrackPoint t0 = new TrackPoint();
|
|
|
b82ef4 |
TrackPoint tp0 = transform(p0);
|
|
|
77c1c7 |
points.Add(tp0);
|
|
|
77c1c7 |
for(int i = 1; i < root.points.Count; ++i) {
|
|
|
b82ef4 |
TrackPoint p2 = root.points[i+1 < root.points.Count ? i+1 : i];
|
|
|
b82ef4 |
TrackPoint tp1 = transform(p1);
|
|
|
b82ef4 |
double dt = p2.time - p0.time;
|
|
|
b82ef4 |
TrackPoint t1 = dt > Geometry.precision
|
|
|
b82ef4 |
? (p2 - p0)*(p1.time - p0.time)/dt
|
|
|
b82ef4 |
: new TrackPoint();
|
|
|
77c1c7 |
addSpline(p0, p1, t0, t1, tp0, tp1, 0.0, 1.0, precisionSqr);
|
|
|
77c1c7 |
|
|
|
77c1c7 |
p0 = p1;
|
|
|
77c1c7 |
p1 = p2;
|
|
|
77c1c7 |
tp0 = tp1;
|
|
|
77c1c7 |
t0 = t1;
|
|
|
77c1c7 |
}
|
|
|
77c1c7 |
}
|
|
|
cfceb0 |
|
|
|
b82ef4 |
public void draw(Cairo.Context context, bool preview = false) {
|
|
|
6148f0 |
if (preview) {
|
|
|
6148f0 |
if (points.Count < 2)
|
|
|
6148f0 |
return;
|
|
|
6148f0 |
context.Save();
|
|
|
6148f0 |
penPreview.apply(context);
|
|
|
6148f0 |
context.MoveTo(points[0].point.x, points[0].point.y);
|
|
|
6148f0 |
for(int i = 1; i < points.Count; ++i)
|
|
|
6148f0 |
context.LineTo(points[i].point.x, points[i].point.y);
|
|
|
6148f0 |
context.Stroke();
|
|
|
6148f0 |
context.Restore();
|
|
|
6148f0 |
} else {
|
|
|
6148f0 |
context.Save();
|
|
|
6148f0 |
pen.apply(context);
|
|
|
6148f0 |
foreach(TrackPoint p in points) {
|
|
|
c66393 |
double t = p.keyState.howLongPressed(Gdk.Key.m)
|
|
|
c66393 |
+ p.buttonState.howLongPressed(3);
|
|
|
c66393 |
double w = p.pressure*pen.width + 5.0*t;
|
|
|
c66393 |
context.Arc(p.point.x, p.point.y, 2.0*w, 0.0, 2.0*Math.PI);
|
|
|
6148f0 |
context.Fill();
|
|
|
6148f0 |
}
|
|
|
6148f0 |
context.Restore();
|
|
|
6148f0 |
}
|
|
|
cfceb0 |
}
|
|
|
cfceb0 |
}
|
|
|
cfceb0 |
}
|
|
|
cfceb0 |
|