Blame mono/Assistance/Track.cs

cfceb0
using System;
cfceb0
using System.Drawing;
cfceb0
using System.Drawing.Imaging;
cfceb0
using System.Collections.Generic;
cfceb0
cfceb0
namespace Assistance {
cfceb0
	public class Track {
cfceb0
		public static readonly Pen pen = new Pen(Brushes.DarkGreen, 3f);
cfceb0
		public static readonly Pen penPreview = new Pen(new SolidBrush(Color.FromArgb(64, Color.DarkGreen)), 1f);
cfceb0
	
cfceb0
		public readonly List<point> points = new List<point>();</point></point>
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
77c1c7
		public Track() { }
77c1c7
77c1c7
		public Track(Track parent, Geometry.TransformFunc transformFunc):
77c1c7
			this()
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
		}
77c1c7
cfceb0
		public Rectangle getBounds() {
cfceb0
			if (points.Count == 0)
cfceb0
				return new Rectangle();
cfceb0
			Rectangle bounds = new Rectangle(points[0]);
cfceb0
			foreach(Point p in points)
cfceb0
				bounds = bounds.expand(p);
cfceb0
			return bounds.inflate(Math.Max(pen.Width, penPreview.Width) + 2.0);
cfceb0
		}
72b17c
72b17c
		public Point transform(Point p) {
72b17c
			return Geometry.transform(transformFuncs, p);
72b17c
		}
72b17c
				
77c1c7
		private void addSpline(Point p0, Point p1, Point t0, Point t1, Point tp0, Point tp1, double l0, double l1, double precisionSqr) {
77c1c7
			if ((tp1 - tp0).lenSqr() < precisionSqr) {
77c1c7
				points.Add(tp1);
77c1c7
			} else {
77c1c7
				double l = 0.5*(l0 + l1);
77c1c7
				Point p = Geometry.splinePoint(p0, p1, t0, t1, l);
72b17c
				Point 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) {
77c1c7
				foreach(Point p in root.points)
77c1c7
					points.Add( Geometry.transform(transformFuncs, p) );
77c1c7
				return;
77c1c7
			}
77c1c7
			
77c1c7
			double precisionSqr = precision * precision;
77c1c7
			Point p0 = root.points[0];
77c1c7
			Point p1 = root.points[1];
77c1c7
			Point t0 = 0.5*(p1 - p0);
77c1c7
			Point tp0 = Geometry.transform(transformFuncs, p0);
77c1c7
			points.Add(tp0);
77c1c7
			for(int i = 1; i < root.points.Count; ++i) {
77c1c7
				Point p2 = root.points[i+1 < root.points.Count ? i+1 : i];
77c1c7
				Point tp1 = Geometry.transform(transformFuncs, p1);
77c1c7
				Point t1 = 0.5*(p2 - p0);
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
cfceb0
		public void draw(Graphics g, bool preview = false) {
cfceb0
			if (points.Count < 2)
cfceb0
				return;
cfceb0
			PointF[] ps = new PointF[points.Count];
cfceb0
			for(int i = 0; i < ps.Length; ++i)
cfceb0
				ps[i] = points[i].toFloat();
cfceb0
			g.DrawLines(preview ? penPreview : pen, ps);
cfceb0
		}
cfceb0
	}
cfceb0
}
cfceb0