254 lines
8.1 KiB
C#
254 lines
8.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
|
|
namespace TestShapeControl
|
|
{
|
|
public partial class Form5 : Form
|
|
{
|
|
//mousedown start pos
|
|
private int sx, sy;
|
|
|
|
//count the number of times the movemove event is fired
|
|
private int num_mousemove = 0;
|
|
|
|
//sampling interval, record the coordinate after this number of mousemove
|
|
private int sampling_interval = 1;
|
|
|
|
//record the trail of the mousemove
|
|
private string str_trail = "";
|
|
|
|
//animation delay per frame in ms;
|
|
private int animation_delay = 0;
|
|
|
|
|
|
public Form5()
|
|
{
|
|
InitializeComponent();
|
|
|
|
}
|
|
|
|
private void ctrl1_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button.Equals(MouseButtons.Left))
|
|
{
|
|
|
|
sx = e.X;
|
|
sy = e.Y;
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void ctrl1_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button.Equals(MouseButtons.Left))
|
|
{
|
|
//num_mousemove is reset to 0 at each sampling interval
|
|
num_mousemove = (num_mousemove + 1) % sampling_interval ;
|
|
|
|
//we record the mouse cooridinate at each sampling interval
|
|
//when num_mousemove is reset to 0
|
|
if (num_mousemove == 0)
|
|
{
|
|
int w=((Control)sender).Width;
|
|
int h=((Control)sender).Height;
|
|
int lastx=((Control)sender).Left + w/2 ;
|
|
int lasty = ((Control)sender).Top +h/2;
|
|
((Control)sender).Left = ((Control)sender).Left + (e.X - sx);
|
|
((Control)sender).Top = ((Control)sender).Top + (e.Y - sy);
|
|
((Control)sender).Refresh();
|
|
|
|
Graphics.FromImage(this.panel1.BackgroundImage).DrawLine(new Pen(Color.White, 3),
|
|
new Point(lastx, lasty),
|
|
new Point(((Control)sender).Left + w / 2, ((Control)sender).Top + h / 2));
|
|
this.Refresh();
|
|
str_trail += lastx + "," + lasty + "|";
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
private void ResetPanelBackground()
|
|
{
|
|
|
|
object o = global::TestShapeControl.Properties.Resources.ResourceManager.GetObject("bluesky");
|
|
|
|
this.panel1.BackgroundImage = new Bitmap(this.Width, this.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
|
|
|
|
|
|
|
Graphics.FromImage(this.panel1.BackgroundImage).DrawImage((Bitmap)o,
|
|
new Rectangle(0, 0, panel1.Width, panel1.Height),
|
|
new Rectangle(0, 0, ((Bitmap)o).Width, ((Bitmap)o).Height),
|
|
GraphicsUnit.Pixel);
|
|
//uncomment line below if you just want a plane background
|
|
// Graphics.FromImage(this.panel1.BackgroundImage).FillRectangle(new SolidBrush(Color.Green), 0, 0, this.Width, this.Height);
|
|
|
|
string s="Drag the red dot on the aeroplane around the image to map out a trail for the areoplane.\nDouble click on red dot to start animation.";
|
|
Graphics.FromImage(this.panel1.BackgroundImage).DrawString(s, new Font(FontFamily.GenericSansSerif,14,FontStyle.Bold),
|
|
new SolidBrush(Color.White), 0, 0);
|
|
|
|
}
|
|
|
|
|
|
private void Form5_Load(object sender, EventArgs e)
|
|
{
|
|
this.panel1.Width = this.Width;
|
|
this.panel1.Height = this.Height;
|
|
this.panel1.Top =0;
|
|
this.panel1.Left =0;
|
|
|
|
this.DoubleBuffered = true;
|
|
|
|
//invoke double buffer
|
|
typeof(Panel).InvokeMember(
|
|
"DoubleBuffered",
|
|
System.Reflection.BindingFlags.NonPublic |
|
|
System.Reflection.BindingFlags.Instance |
|
|
System.Reflection.BindingFlags.SetProperty,
|
|
null,
|
|
panel1,
|
|
new object[] { true });
|
|
|
|
ResetPanelBackground();
|
|
}
|
|
|
|
private double RadianToDegree(double angle)
|
|
{
|
|
return angle * (180.0 / Math.PI);
|
|
}
|
|
|
|
//Land the butterfly
|
|
private void Land(Point p0)
|
|
{
|
|
ctrlPlane.Left = p0.X - ctrlPlane.Width / 2;
|
|
ctrlPlane.Top = p0.Y - ctrlPlane.Height / 2;
|
|
ctrlPlane.Refresh();
|
|
}
|
|
|
|
//Move the butterfly, changing it orientation
|
|
private void Fly(Point p0, Point p1)
|
|
{
|
|
//calculate the angle to rotate so that the butterfly
|
|
//will be in the correct orientation as the direction
|
|
//of flight
|
|
|
|
double deltaX=(p1.X - p0.X);
|
|
double deltaY=(p1.Y - p0.Y);
|
|
|
|
//may not be necessary as Atan2 function probably handle div by 0
|
|
//double epsilon = 0.00001f;
|
|
//if (Math.Abs(deltaX) < epsilon && Math.Abs(deltaY) < epsilon)
|
|
// return;
|
|
|
|
|
|
double theta= Math.Atan2(deltaY,deltaX );
|
|
|
|
//if (theta == double.NaN)
|
|
// return;
|
|
|
|
double angle = RadianToDegree(theta);
|
|
|
|
|
|
//redefine angle to be between -180 and 180
|
|
if (angle > 180)
|
|
angle = angle - 360;
|
|
else
|
|
{
|
|
if (angle < -180)
|
|
angle = 360 + angle;
|
|
}
|
|
|
|
// System.Diagnostics.Debug.Print(""+ theta +"-->" + angle);
|
|
|
|
//set the min angle change
|
|
|
|
int deltaAngle = (int)Math.Abs(angle - ctrlPlane.ShapeImageRotation);
|
|
|
|
if(deltaAngle>=5)
|
|
ctrlPlane.ShapeImageRotation = (int)angle;
|
|
|
|
//set the position and orientation of the butterfly
|
|
|
|
ctrlPlane.Left = p0.X - ctrlPlane.Width / 2;
|
|
ctrlPlane.Top = p0.Y - ctrlPlane.Height / 2;
|
|
ctrlPlane.Refresh();
|
|
|
|
}
|
|
|
|
//trace out the trail, moving the plane along it
|
|
private void TraceTrail()
|
|
{
|
|
if(str_trail =="") return;
|
|
|
|
ResetPanelBackground();
|
|
|
|
//note that v[v.Length-1], the last split part is always ""
|
|
//as str_trail always end with "|" because we append "|"
|
|
//after each set of x,y coordinates to str_trail in the mousemove event handler
|
|
|
|
var v = str_trail.Split('|');
|
|
|
|
//we need at lest 5 points
|
|
if (v.Length < 5) return;
|
|
|
|
var v1=v[0].Split(',');
|
|
|
|
//default dummy values for init purposes
|
|
var v2 = v1;
|
|
var v3 = v1;
|
|
|
|
//p0 is start of trail segment
|
|
Point p0 = new Point(int.Parse(v1[0]),int.Parse(v1[1]));
|
|
|
|
Point p1 = Point.Empty;// new Point(int.Parse(v2[0]), int.Parse(v2[1]));
|
|
Point p2 = Point.Empty; // new Point(int.Parse(v3[0]), int.Parse(v3[1]));
|
|
|
|
//p3 is end of trail segment
|
|
Point p3 = Point.Empty;
|
|
|
|
for (int i = 1; i < v.Length - 4; i++)
|
|
{
|
|
v1= v[i].Split(',');
|
|
v2 = v[i + 1].Split(',');
|
|
v3 = v[i + 2].Split(',');
|
|
|
|
p1 = new Point(int.Parse(v1[0]), int.Parse(v1[1]));
|
|
p2 = new Point(int.Parse(v2[0]), int.Parse(v2[1]));
|
|
p3 = new Point(int.Parse(v3[0]), int.Parse(v3[1]));
|
|
|
|
Fly(p0, p3);
|
|
|
|
//move to the next point
|
|
p0 = new Point(p1.X, p1.Y);
|
|
|
|
this.panel1.Refresh();
|
|
|
|
//manage the speed of animation
|
|
System.Threading.Thread.Sleep(animation_delay);
|
|
}
|
|
|
|
Land(p1);
|
|
|
|
//clear the trail
|
|
str_trail = "";
|
|
}
|
|
|
|
private void ctrl1_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
TraceTrail();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|