|
|
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 |
|