Blame mono/Autospline/MainWindow.cs

e6a405
using System;
e6a405
using System.Drawing;
e6a405
using System.Drawing.Imaging;
e6a405
using System.Windows.Forms;
e6a405
using System.Collections.Generic;
e6a405
e6a405
namespace Autospline {
e6a405
	public struct Segment {
e6a405
		public double previous;
e6a405
		public double current;
e6a405
		public double next;
e6a405
		public double nextnext;
e6a405
e6a405
		public static double get(double s, double p0, double pm, double p1) {
e6a405
			return p0*(1.0-s)*(1.0-s) + 2.0*pm*(1.0-s)*s + p1*s*s;
e6a405
		}
e6a405
e6a405
		public static double get(double s, double p0, double p1, double t0, double t1) {
e6a405
			double h0 =  2.0*s*s*s - 3.0*s*s + 1.0;
e6a405
			double h1 = -2.0*s*s*s + 3.0*s*s;
e6a405
			double h2 =      s*s*s - 2.0*s*s + s;
e6a405
			double h3 =      s*s*s -     s*s;
e6a405
			double p = h0*p0 + h1*p1 + h2*t0 + h3*t1;
e6a405
			return p;
e6a405
		}
e6a405
e6a405
		public double get(double s) {
e6a405
			return get(s, current, next, current - previous, next - current);
e6a405
		}
e6a405
e6a405
		public double getCool(double s) {
e6a405
			return get(s, current, next, 0.5*(next - previous), 0.5*(nextnext - current));
e6a405
		}
e6a405
e6a405
		public double getCool2(double s) {
e6a405
			return get(s, 0.5*(previous + current), current, 0.5*(current + next));
e6a405
		}
e6a405
	}
e6a405
e6a405
	public struct Segment2d {
e6a405
		public Segment x;
e6a405
		public Segment y;
e6a405
	}
e6a405
e6a405
	public class MainWindow : Form {
e6a405
        static public void Main() { Application.Run(new MainWindow()); }
e6a405
e6a405
		bool pressed = false;
e6a405
		List<segment2d> segments = new List<segment2d>();</segment2d></segment2d>
e6a405
		Bitmap buffer;
e6a405
e6a405
		void newCurve(double x, double y) {
e6a405
			Segment2d segment;
e6a405
			segment.x.previous = segment.x.current = segment.x.next = segment.x.nextnext = x;
e6a405
			segment.y.previous = segment.y.current = segment.y.next = segment.y.nextnext = y;
e6a405
			segments.Add(segment);
e6a405
		}
e6a405
e6a405
		void addPoint(double x, double y) {
e6a405
			Segment2d previous = segments[segments.Count - 1];
e6a405
			previous.x.nextnext = x;
e6a405
			previous.y.nextnext = y;
e6a405
			segments[segments.Count - 1] = previous;
e6a405
e6a405
			Segment2d segment;
e6a405
			segment.y.nextnext = y;
e6a405
			segment.x.next = segment.x.nextnext = x;
e6a405
			segment.y.next = segment.y.nextnext = y;
e6a405
			segment.x.current = previous.x.next;
e6a405
			segment.y.current = previous.y.next;
e6a405
			segment.x.previous = previous.x.current;
e6a405
			segment.y.previous = previous.y.current;
e6a405
			segments.Add(segment);
e6a405
		}
e6a405
e6a405
		public MainWindow() {
e6a405
			OnResize(this, new EventArgs());
e6a405
            Paint += OnPaint;
e6a405
			MouseMove += OnMouseMove;
e6a405
			MouseDown += OnMouseDown;
e6a405
			MouseUp += OnMouseUp;
e6a405
			Resize += OnResize;
e6a405
            WindowState = FormWindowState.Maximized;
e6a405
        }
e6a405
e6a405
		public void OnResize(Object sender, EventArgs e) {
e6a405
			buffer = new Bitmap(ClientSize.Width, ClientSize.Height);
e6a405
		}
e6a405
e6a405
        public void OnPaint(Object sender, PaintEventArgs e) {
e6a405
			Graphics g = Graphics.FromImage(buffer);
e6a405
            Draw(g);
e6a405
			g.Flush();
e6a405
			e.Graphics.DrawImageUnscaled(buffer, 0, 0);
e6a405
        }
e6a405
e6a405
		public void OnMouseDown(Object sender, MouseEventArgs e) {
e6a405
			if (e.Button == MouseButtons.Left) {
e6a405
				newCurve(e.X, e.Y);
e6a405
				pressed = true;
e6a405
				Invalidate();
e6a405
			} else
e6a405
			if (e.Button == MouseButtons.Right) {
e6a405
				segments.Clear();
e6a405
				if (pressed) newCurve(e.X, e.Y);
e6a405
				Invalidate();
e6a405
			}
e6a405
		}
e6a405
e6a405
		public void OnMouseUp(Object sender, MouseEventArgs e) {
e6a405
			if (e.Button == MouseButtons.Left && pressed) {
e6a405
				addPoint(e.X, e.Y);
e6a405
				pressed = false;
e6a405
				Invalidate();
e6a405
			}
e6a405
		}
e6a405
e6a405
		public void OnMouseMove(Object sender, MouseEventArgs e) {
e6a405
			if (pressed) {
e6a405
				addPoint(e.X, e.Y);
e6a405
				Invalidate();
e6a405
			}
e6a405
        }
e6a405
e6a405
        public void Draw(Graphics g) {
e6a405
            g.Clear(Color.White);
e6a405
			g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
e6a405
			int count = 100;
e6a405
			double r = 2.0;
e6a405
			double l = 2.0;
e6a405
e6a405
			Pen pen = new Pen(Color.FromArgb(128, 128, 128, 128));
e6a405
			Pen cool = new Pen(Color.FromArgb(128, 0, 0, 255));
e6a405
e6a405
			foreach(Segment2d segment in segments) {
e6a405
				double x0 = segment.x.get(0.0);
e6a405
				double y0 = segment.y.get(0.0);
e6a405
				for(int i = 1; i <= count; ++i) {
e6a405
					double x1 = segment.x.get((double)i/(double)count);
e6a405
					double y1 = segment.y.get((double)i/(double)count);
e6a405
					if (i == count || (x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0) > l*l) {
e6a405
						g.DrawLine(pen, (float)x0, (float)y0, (float)x1, (float)y1);
e6a405
						x0 = x1;
e6a405
						y0 = y1;
e6a405
					}
e6a405
				}
e6a405
e6a405
				x0 = segment.x.getCool2(0.0);
e6a405
				y0 = segment.y.getCool2(0.0);
e6a405
				for(int i = 1; i <= count; ++i) {
e6a405
					double x1 = segment.x.getCool2((double)i/(double)count);
e6a405
					double y1 = segment.y.getCool2((double)i/(double)count);
e6a405
					if (i == count || (x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0) > l*l) {
e6a405
						g.DrawLine(cool, (float)x0, (float)y0, (float)x1, (float)y1);
e6a405
						x0 = x1;
e6a405
						y0 = y1;
e6a405
					}
e6a405
				}
e6a405
e6a405
				g.FillEllipse(
e6a405
					Brushes.Black,
e6a405
					(float)(segment.x.current - r), (float)(segment.y.current - r),
e6a405
					(float)(2.0*r), (float)(2.0*r) );
e6a405
				g.FillEllipse(
e6a405
					Brushes.Black,
e6a405
					(float)(segment.x.next - r), (float)(segment.y.next - r),
e6a405
					(float)(2.0*r), (float)(2.0*r) );
e6a405
			}
e6a405
        }
e6a405
    }
e6a405
}
e6a405