如何使用鼠标画线和每 5 度锁定角度
How to drawline using mouse and locking angle each 5 degrees
我有一个问题,我需要使用鼠标画一条线并每 5 度锁定一次角度。
我可以水平和垂直锁定线,但我无法锁定角度
if (e.Button == MouseButtons.Left)
{
if (e.Button != MouseButtons.Left)
{
return;
}
startLine = new Point();
endLine = new Point();
if (ModifierKeys == Keys.Control)
{
pointLineDest = new Point(e.X, pointLineOrigin.Y);
}
else if (ModifierKeys == (Keys.Control | Keys.Shift))
{
pointLineDest = new Point(pointLineOrigin.X, e.Y);
}
else
{
pointLineDest = e.Location;
Globals.AddOutputLog($"{CalculeAngle(pointLineOrigin, pointLineDest)}");
}
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
canvas.Refresh();
}
在上面的代码中,我在按住 ctrl 时锁定到 0 度,在按住 shift + ctrl 时锁定到 90 度。
但是我需要允许用户将线移动 5 度,如果他愿意的话,我不知道该怎么做。
有人能帮帮我吗?
对不起我的英语。
编辑----------------
我想我解决了问题,但还有一个细节。
使用follow方法移动鼠标可以旋转5度
static Point RotatePoint(Point pointToRotate, Point centerPoint, double angleInDegrees)
{
double angleInRadians = angleInDegrees * (Math.PI / 180);
double cosTheta = Math.Cos(angleInRadians);
double sinTheta = Math.Sin(angleInRadians);
return new Point
{
X = (int)(cosTheta * (pointToRotate.X - centerPoint.X) -
sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),
Y = (int)(sinTheta * (pointToRotate.X - centerPoint.X) +
cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y)
};
}
我这样调用 mouseMove 事件中的方法:
Point tempP = new Point(e.X, pointLineOrigin.Y);
int dy = e.Y - pointLineOrigin.Y;
int dir = (dy > 0) ? -1 : 1;
if (dir == -1)
pointLineDest = RotatePoint(tempP, pointLineOrigin, -5);
else
pointLineDest = RotatePoint(tempP, pointLineOrigin, 5);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
所以我有一条线,从 0 度开始,如果我向上移动鼠标,它会变成 5 度,如果我向下移动,它会变成 -5 度。完美的!但是,如果我继续向上或向下移动鼠标,倾斜度不会增加 5 度。也就是说,我只能向上或向下移动5度一次。
如何在移动鼠标时保持线条旋转?
编辑--------------------
好的,我在@amin29 a 的帮助下得到了它。谢谢队友!
_rad5 = DegreeToRadian(5);
float rad = (float)Math.Atan2(e.Y - pointLineOrigin.Y, e.X - pointLineOrigin.X);
int x = pointLineOrigin.X;
int y = pointLineOrigin.Y;
float angle = rad;
double step = _rad5;
double finalAngle;
double c = rad % _rad5;
finalAngle = angle - c;
if (c > step / 2)
finalAngle = (angle - c) + step;
double length = Math.Sqrt((Math.Pow(pointLineOrigin.X - e.X, 2) + Math.Pow(pointLineOrigin.Y - e.Y, 2)));
// Create points that define line.
Point point1 = new Point(x, y);
Point point2 = new Point((int)(x + Math.Cos(finalAngle) * length), (int)(y + Math.Sin(finalAngle) * length));
startLine = point1;
endLine = point2;
使用这些方法
private double DegreeToRadian(double degree)
{
return degree * Math.PI / 180;
}
private Point LockInAngle(Point pt, double degree)
{
int y = (int)(pt.X * Math.Tan(DegreeToRadian(degree)));
return new Point(pt.X, y);
}
你的代码应该是这样的
if (e.Button == MouseButtons.Left)
{
startLine = new Point();
endLine = new Point();
if (ModifierKeys == Keys.Control)
{
pointLineDest = new Point(e.X, pointLineOrigin.Y);
}
else if (ModifierKeys == (Keys.Control | Keys.Shift))
{
pointLineDest = new Point(pointLineOrigin.X, e.Y);
}
else
{
pointLineDest = LockInAngle(e.Location, 5);
}
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
canvas.Refresh();
}
编辑---------------------------------------- --------------
检查此代码,它是 windows 形式
public partial class Form1 : Form
{
Point startLine;
Point endLine;
Point pointLineDest;
Point pointLineOrigin;
double _rad5;
public Form1()
{
InitializeComponent();
startLine = Point.Empty;
endLine = Point.Empty;
pointLineOrigin = new Point(Width / 2, Height / 2);
Paint += Form1_Paint;
SizeChanged += Form1_SizeChanged;
_rad5 = DegreeToRadian(5);
}
private void Form1_SizeChanged(object sender, EventArgs e)
{
pointLineOrigin = new Point(Width / 2, Height / 2);
Invalidate(false);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; ;
e.Graphics.DrawLine(Pens.Red, startLine, endLine);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (ModifierKeys == Keys.Control)
{
pointLineDest = new Point(e.X, pointLineOrigin.Y);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
else if (ModifierKeys == (Keys.Control | Keys.Shift))
{
pointLineDest = new Point(pointLineOrigin.X, e.Y);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
else
{
float rad =(float) Math.Atan2(e.Y - pointLineOrigin.Y, e.X - pointLineOrigin.X);
if (Math.Abs(rad % _rad5) < 0.005)
{
pointLineDest = e.Location;
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
}
}
private double DegreeToRadian(double degree)
{
return degree * Math.PI / 180;
}
}
编辑----------
我编辑了你的代码以获得更好的性能,如果你想使用左键单击,你可以添加 MouseUp 和 MouseDown 事件。 (如果您的 canvas 有 DoubleBuffered 属性 将其设置为 true)
public partial class Form1 : Form
{
bool _isMouseDown;
Point startLine;
Point endLine;
Point pointLineDest;
Point pointLineOrigin;
float _rad5;
float _rad5DivideBy2;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
_rad5 = DegreeToRadian(5);
_rad5DivideBy2 = _rad5 / 2;
startLine = Point.Empty;
endLine = Point.Empty;
pointLineOrigin = new Point(Width / 2, Height / 2);
Paint += Form1_Paint;
SizeChanged += Form1_SizeChanged;
}
private void Form1_SizeChanged(object sender, EventArgs e)
{
pointLineOrigin = new Point(Width / 2, Height / 2);
Invalidate(false);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
e.Graphics.DrawLine(Pens.Red, startLine, endLine);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_isMouseDown = true;
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_isMouseDown = false;
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (_isMouseDown)
{
if (ModifierKeys == Keys.Control)
{
pointLineDest = new Point(e.X, pointLineOrigin.Y);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
else if (ModifierKeys == (Keys.Control | Keys.Shift))
{
pointLineDest = new Point(pointLineOrigin.X, e.Y);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
else
{
int dx = e.X - pointLineOrigin.X;
int dy = e.Y - pointLineOrigin.Y;
float rad = (float)Math.Atan2(dy, dx);
if (rad < 0)
{
rad += (float)(2 * Math.PI);
}
float rem = rad % _rad5;
float finalAngle = rad - rem;
if (rem > _rad5DivideBy2)
{
finalAngle += _rad5;
}
float length = (float)Math.Sqrt(dx * dx + dy * dy);
pointLineDest = new Point((int)(Math.Cos(finalAngle) * length), (int)(Math.Sin(finalAngle) * length));
pointLineDest.Offset(pointLineOrigin);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
}
}
private float DegreeToRadian(float degree)
{
return (float)(degree * Math.PI / 180);
}
}
我有一个问题,我需要使用鼠标画一条线并每 5 度锁定一次角度。
我可以水平和垂直锁定线,但我无法锁定角度
if (e.Button == MouseButtons.Left)
{
if (e.Button != MouseButtons.Left)
{
return;
}
startLine = new Point();
endLine = new Point();
if (ModifierKeys == Keys.Control)
{
pointLineDest = new Point(e.X, pointLineOrigin.Y);
}
else if (ModifierKeys == (Keys.Control | Keys.Shift))
{
pointLineDest = new Point(pointLineOrigin.X, e.Y);
}
else
{
pointLineDest = e.Location;
Globals.AddOutputLog($"{CalculeAngle(pointLineOrigin, pointLineDest)}");
}
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
canvas.Refresh();
}
在上面的代码中,我在按住 ctrl 时锁定到 0 度,在按住 shift + ctrl 时锁定到 90 度。 但是我需要允许用户将线移动 5 度,如果他愿意的话,我不知道该怎么做。
有人能帮帮我吗? 对不起我的英语。
编辑----------------
我想我解决了问题,但还有一个细节。
使用follow方法移动鼠标可以旋转5度
static Point RotatePoint(Point pointToRotate, Point centerPoint, double angleInDegrees)
{
double angleInRadians = angleInDegrees * (Math.PI / 180);
double cosTheta = Math.Cos(angleInRadians);
double sinTheta = Math.Sin(angleInRadians);
return new Point
{
X = (int)(cosTheta * (pointToRotate.X - centerPoint.X) -
sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),
Y = (int)(sinTheta * (pointToRotate.X - centerPoint.X) +
cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y)
};
}
我这样调用 mouseMove 事件中的方法:
Point tempP = new Point(e.X, pointLineOrigin.Y);
int dy = e.Y - pointLineOrigin.Y;
int dir = (dy > 0) ? -1 : 1;
if (dir == -1)
pointLineDest = RotatePoint(tempP, pointLineOrigin, -5);
else
pointLineDest = RotatePoint(tempP, pointLineOrigin, 5);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
所以我有一条线,从 0 度开始,如果我向上移动鼠标,它会变成 5 度,如果我向下移动,它会变成 -5 度。完美的!但是,如果我继续向上或向下移动鼠标,倾斜度不会增加 5 度。也就是说,我只能向上或向下移动5度一次。
如何在移动鼠标时保持线条旋转?
编辑--------------------
好的,我在@amin29 a 的帮助下得到了它。谢谢队友!
_rad5 = DegreeToRadian(5);
float rad = (float)Math.Atan2(e.Y - pointLineOrigin.Y, e.X - pointLineOrigin.X);
int x = pointLineOrigin.X;
int y = pointLineOrigin.Y;
float angle = rad;
double step = _rad5;
double finalAngle;
double c = rad % _rad5;
finalAngle = angle - c;
if (c > step / 2)
finalAngle = (angle - c) + step;
double length = Math.Sqrt((Math.Pow(pointLineOrigin.X - e.X, 2) + Math.Pow(pointLineOrigin.Y - e.Y, 2)));
// Create points that define line.
Point point1 = new Point(x, y);
Point point2 = new Point((int)(x + Math.Cos(finalAngle) * length), (int)(y + Math.Sin(finalAngle) * length));
startLine = point1;
endLine = point2;
使用这些方法
private double DegreeToRadian(double degree)
{
return degree * Math.PI / 180;
}
private Point LockInAngle(Point pt, double degree)
{
int y = (int)(pt.X * Math.Tan(DegreeToRadian(degree)));
return new Point(pt.X, y);
}
你的代码应该是这样的
if (e.Button == MouseButtons.Left)
{
startLine = new Point();
endLine = new Point();
if (ModifierKeys == Keys.Control)
{
pointLineDest = new Point(e.X, pointLineOrigin.Y);
}
else if (ModifierKeys == (Keys.Control | Keys.Shift))
{
pointLineDest = new Point(pointLineOrigin.X, e.Y);
}
else
{
pointLineDest = LockInAngle(e.Location, 5);
}
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
canvas.Refresh();
}
编辑---------------------------------------- -------------- 检查此代码,它是 windows 形式
public partial class Form1 : Form
{
Point startLine;
Point endLine;
Point pointLineDest;
Point pointLineOrigin;
double _rad5;
public Form1()
{
InitializeComponent();
startLine = Point.Empty;
endLine = Point.Empty;
pointLineOrigin = new Point(Width / 2, Height / 2);
Paint += Form1_Paint;
SizeChanged += Form1_SizeChanged;
_rad5 = DegreeToRadian(5);
}
private void Form1_SizeChanged(object sender, EventArgs e)
{
pointLineOrigin = new Point(Width / 2, Height / 2);
Invalidate(false);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; ;
e.Graphics.DrawLine(Pens.Red, startLine, endLine);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (ModifierKeys == Keys.Control)
{
pointLineDest = new Point(e.X, pointLineOrigin.Y);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
else if (ModifierKeys == (Keys.Control | Keys.Shift))
{
pointLineDest = new Point(pointLineOrigin.X, e.Y);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
else
{
float rad =(float) Math.Atan2(e.Y - pointLineOrigin.Y, e.X - pointLineOrigin.X);
if (Math.Abs(rad % _rad5) < 0.005)
{
pointLineDest = e.Location;
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
}
}
private double DegreeToRadian(double degree)
{
return degree * Math.PI / 180;
}
}
编辑---------- 我编辑了你的代码以获得更好的性能,如果你想使用左键单击,你可以添加 MouseUp 和 MouseDown 事件。 (如果您的 canvas 有 DoubleBuffered 属性 将其设置为 true)
public partial class Form1 : Form
{
bool _isMouseDown;
Point startLine;
Point endLine;
Point pointLineDest;
Point pointLineOrigin;
float _rad5;
float _rad5DivideBy2;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
_rad5 = DegreeToRadian(5);
_rad5DivideBy2 = _rad5 / 2;
startLine = Point.Empty;
endLine = Point.Empty;
pointLineOrigin = new Point(Width / 2, Height / 2);
Paint += Form1_Paint;
SizeChanged += Form1_SizeChanged;
}
private void Form1_SizeChanged(object sender, EventArgs e)
{
pointLineOrigin = new Point(Width / 2, Height / 2);
Invalidate(false);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
e.Graphics.DrawLine(Pens.Red, startLine, endLine);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_isMouseDown = true;
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_isMouseDown = false;
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (_isMouseDown)
{
if (ModifierKeys == Keys.Control)
{
pointLineDest = new Point(e.X, pointLineOrigin.Y);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
else if (ModifierKeys == (Keys.Control | Keys.Shift))
{
pointLineDest = new Point(pointLineOrigin.X, e.Y);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
else
{
int dx = e.X - pointLineOrigin.X;
int dy = e.Y - pointLineOrigin.Y;
float rad = (float)Math.Atan2(dy, dx);
if (rad < 0)
{
rad += (float)(2 * Math.PI);
}
float rem = rad % _rad5;
float finalAngle = rad - rem;
if (rem > _rad5DivideBy2)
{
finalAngle += _rad5;
}
float length = (float)Math.Sqrt(dx * dx + dy * dy);
pointLineDest = new Point((int)(Math.Cos(finalAngle) * length), (int)(Math.Sin(finalAngle) * length));
pointLineDest.Offset(pointLineOrigin);
startLine = new Point(pointLineOrigin.X, pointLineOrigin.Y);
endLine = new Point(pointLineDest.X, pointLineDest.Y);
Invalidate(false);
}
}
}
private float DegreeToRadian(float degree)
{
return (float)(degree * Math.PI / 180);
}
}