如何计算 C# 中的旋转图像坐标?
How to count rotated image coordinates in C#?
我正在编写程序通过使用 x y 坐标在图片框中绘制图像来绘制一些线条。图像将是可调整的,因此可以调整大小或旋转,但我希望绘制的线条跟随图像,而不是停留在图片框坐标上。当放大或缩小时,线条仍然跟随图像,但旋转时它随机跳跃而不是跟随图像。
绘制 3 条线的默认程序
缩放后的图像,线条仍然存在
图像旋转 10 度。线条跳转到随机位置。
我目前正在使用这个带有 2 个坐标的坐标来形成一条线,但它使坐标随机地到处跳跃,而不是随图像一起旋转。
这是黑线 1 的代码。
---编辑---
这是顺时针旋转的代码,但不知何故它逆时针旋转。 angle2 的值仍然未知,32 是通过逆时针旋转一个一个地尝试的最接近的位置。坐标没有像以前那样随机跳跃,现在它随着图片旋转,但旋转的位置仍然不正确。旋转 360 度后,坐标位置与原始位置略有移动。每次旋转都是逆时针的。
在角度 2
中以 32 值旋转之前的原始值
旋转360度后
float x = (float)bmp.Width / 2;
float y = (float)bmp.Height / 2;
ang = ang + 10;
double ang2 = 32;
double newLine1X1 = (line1X1 - x) * Math.Cos(ang2 /180) + (line1Y1 - y) * Math.Sin(ang2 /180) + x;
double newLine1Y1 = -(line1X1 - x) * Math.Sin(ang2 /180) + (line1Y1 - y) * Math.Cos(ang2 /180) + y;
double newLine1X2 = (line1X2 - x) * Math.Cos(ang2 /180) + (line1Y2 - y) * Math.Sin(ang2 /180) + x;
double newLine1Y2 = -(line1X2 - x) * Math.Sin(ang2 /180) + (line1Y2 - y) * Math.Cos(ang2 /180) + y;
line1X1 = (int)newLine1X1;
line1Y1 = (int)newLine1Y1;
line1X2 = (int)newLine1X2;
line1Y2 = (int)newLine1Y2;
顺时针旋转代码
float x = (float)bmp.Width / 2;
float y = (float)bmp.Height / 2;
ang = ang - 10;
double ang2 = -32;
double newLine1X1 = (line1X1 - x) * Math.Cos(ang2 /180) - (line1Y1 - y) * Math.Sin(ang2 /180) + x;
double newLine1Y1 = (line1X1 - x) * Math.Sin(ang2 /180) + (line1Y1 - y) * Math.Cos(ang2 /180) + y;
double newLine1X2 = (line1X2 - x) * Math.Cos(ang2 /180) - (line1Y2 - y) * Math.Sin(ang2 /180) + x;
double newLine1Y2 = (line1X2 - x) * Math.Sin(ang2 /180) + (line1Y2 - y) * Math.Cos(ang2 /180) + y;
line1X1 = (int)newLine1X1;
line1Y1 = (int)newLine1Y1;
line1X2 = (int)newLine1X2;
line1Y2 = (int)newLine1Y2;
逆时针旋转代码
谁能告诉我如何解决这个旋转错误?非常感谢你。
你要的是一个变换矩阵和一个偏移向量
https://en.wikipedia.org/wiki/Transformation_matrix#Rotation
P_x为点P的x坐标,P_y为其y坐标
PT_x 和 PT_y 应为变换后的坐标
O_x和O_y为偏移点(图片旋转的点)
d 应为旋转角度...
PT_x = (P_x - O_x) * cos(d) + (P_y - O_y) * sin(d) + O_x
PT_y = -(P_x - O_x) * sin(d) + (P_y - O_y) * cos(d) + O_y
示例:一个旋转的盒子,在盒子旋转时有一条线指向同一点
using System;
using System.Drawing;
using System.Windows.Forms;
namespace SoExamples.Rotation
{
public class Form1 : Form
{
Bitmap bmp = new Bitmap(100, 100); //placeholder... our rotating box
Point p1 = new Point(80,5);//a point in our rotating box
int deg = 0;//the current rotation of the box in degrees 0...359
Point start;//a point to start drawing a line...
public Form1()
{
InitializeComponent();
//preparing our dummy box
using (var graphics = Graphics.FromImage(bmp))
{
graphics.Clear(Color.LightBlue);// a background color...
graphics.DrawString("X", DefaultFont, Brushes.White, p1);
}
//calculating the start point for a line...
start = new Point(label1.Location.X + label1.Width / 2, label1.Location.Y + label1.Height); //in the middle under the label
}
/// <summary>
/// timer handler, executed every time the timer is ellapsed ... every 100ms
/// </summary>
private void timer1_Tick(object sender, EventArgs e)
{
deg++;//let's rotate...
deg %= 360;//0...359
Invalidate(true);//queue for re-drawing
}
/// <summary>
/// custom painting for the Form ... called every time the form is re-drawn
/// </summary>
private void Form1_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
g.Clear(BackColor);
Point drawTo = new Point(Width / 2, Height / 2);//we want to draw the box in the center of the form
drawTo.Offset(-bmp.Width / 2, -bmp.Height / 2);//...but we need to specify the upper left corner
Point rotateAround = new Point(Width / 2, Height / 2);//we want to rotate the box around the center
g.TranslateTransform(-rotateAround.X, -rotateAround.Y); //translate the rotateAround point as 0,0
g.RotateTransform(-deg, System.Drawing.Drawing2D.MatrixOrder.Append);//rotate
g.TranslateTransform(rotateAround.X, rotateAround.Y, System.Drawing.Drawing2D.MatrixOrder.Append);//translate back
g.DrawImageUnscaled(bmp, drawTo);//draw the box with respect to current transforms...
g.ResetTransform();//now back to our original coordinate-space
var P = new Point(drawTo.X + p1.X, drawTo.Y + p1.Y); //the point we want to point to in the original coordinate-space (before rotation)
var O = rotateAround;
var rad = deg * Math.PI / 180d; //System.Math want's our angle in radians
//coordinate calculation for a rotation around O
//PT_x = (P_x - O_x) * cos(d) + (P_y - O_y) * sin(d) + O_x
//PT_y = -(P_x - O_x) * sin(d) + (P_y - O_y) * cos(d) + O_y
var PT_x = (P.X - O.X) * Math.Cos(rad) + (P.Y - O.Y) * Math.Sin(rad) + O.X;
var PT_y = -(P.X - O.X) * Math.Sin(rad) + (P.Y - O.Y) * Math.Cos(rad) + O.Y;
drawTo = new Point((int)PT_x, (int)PT_y);
g.DrawLine(Pens.Black, start, drawTo); // draw a line to the calculated point
}
//boiler plate code follows...
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.label1 = new System.Windows.Forms.Label();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(41, 43);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(197, 13);
this.label1.TabIndex = 1;
this.label1.Text = "Some fixed point to start drawing a line to the top left corner of a 'X' in a rotating box...";
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Timer timer1;
}
}
我正在编写程序通过使用 x y 坐标在图片框中绘制图像来绘制一些线条。图像将是可调整的,因此可以调整大小或旋转,但我希望绘制的线条跟随图像,而不是停留在图片框坐标上。当放大或缩小时,线条仍然跟随图像,但旋转时它随机跳跃而不是跟随图像。
我目前正在使用这个带有 2 个坐标的坐标来形成一条线,但它使坐标随机地到处跳跃,而不是随图像一起旋转。 这是黑线 1 的代码。
---编辑---
这是顺时针旋转的代码,但不知何故它逆时针旋转。 angle2 的值仍然未知,32 是通过逆时针旋转一个一个地尝试的最接近的位置。坐标没有像以前那样随机跳跃,现在它随着图片旋转,但旋转的位置仍然不正确。旋转 360 度后,坐标位置与原始位置略有移动。每次旋转都是逆时针的。
float x = (float)bmp.Width / 2;
float y = (float)bmp.Height / 2;
ang = ang + 10;
double ang2 = 32;
double newLine1X1 = (line1X1 - x) * Math.Cos(ang2 /180) + (line1Y1 - y) * Math.Sin(ang2 /180) + x;
double newLine1Y1 = -(line1X1 - x) * Math.Sin(ang2 /180) + (line1Y1 - y) * Math.Cos(ang2 /180) + y;
double newLine1X2 = (line1X2 - x) * Math.Cos(ang2 /180) + (line1Y2 - y) * Math.Sin(ang2 /180) + x;
double newLine1Y2 = -(line1X2 - x) * Math.Sin(ang2 /180) + (line1Y2 - y) * Math.Cos(ang2 /180) + y;
line1X1 = (int)newLine1X1;
line1Y1 = (int)newLine1Y1;
line1X2 = (int)newLine1X2;
line1Y2 = (int)newLine1Y2;
顺时针旋转代码
float x = (float)bmp.Width / 2;
float y = (float)bmp.Height / 2;
ang = ang - 10;
double ang2 = -32;
double newLine1X1 = (line1X1 - x) * Math.Cos(ang2 /180) - (line1Y1 - y) * Math.Sin(ang2 /180) + x;
double newLine1Y1 = (line1X1 - x) * Math.Sin(ang2 /180) + (line1Y1 - y) * Math.Cos(ang2 /180) + y;
double newLine1X2 = (line1X2 - x) * Math.Cos(ang2 /180) - (line1Y2 - y) * Math.Sin(ang2 /180) + x;
double newLine1Y2 = (line1X2 - x) * Math.Sin(ang2 /180) + (line1Y2 - y) * Math.Cos(ang2 /180) + y;
line1X1 = (int)newLine1X1;
line1Y1 = (int)newLine1Y1;
line1X2 = (int)newLine1X2;
line1Y2 = (int)newLine1Y2;
逆时针旋转代码
谁能告诉我如何解决这个旋转错误?非常感谢你。
你要的是一个变换矩阵和一个偏移向量
https://en.wikipedia.org/wiki/Transformation_matrix#Rotation
P_x为点P的x坐标,P_y为其y坐标
PT_x 和 PT_y 应为变换后的坐标
O_x和O_y为偏移点(图片旋转的点)
d 应为旋转角度...
PT_x = (P_x - O_x) * cos(d) + (P_y - O_y) * sin(d) + O_x
PT_y = -(P_x - O_x) * sin(d) + (P_y - O_y) * cos(d) + O_y
示例:一个旋转的盒子,在盒子旋转时有一条线指向同一点
using System;
using System.Drawing;
using System.Windows.Forms;
namespace SoExamples.Rotation
{
public class Form1 : Form
{
Bitmap bmp = new Bitmap(100, 100); //placeholder... our rotating box
Point p1 = new Point(80,5);//a point in our rotating box
int deg = 0;//the current rotation of the box in degrees 0...359
Point start;//a point to start drawing a line...
public Form1()
{
InitializeComponent();
//preparing our dummy box
using (var graphics = Graphics.FromImage(bmp))
{
graphics.Clear(Color.LightBlue);// a background color...
graphics.DrawString("X", DefaultFont, Brushes.White, p1);
}
//calculating the start point for a line...
start = new Point(label1.Location.X + label1.Width / 2, label1.Location.Y + label1.Height); //in the middle under the label
}
/// <summary>
/// timer handler, executed every time the timer is ellapsed ... every 100ms
/// </summary>
private void timer1_Tick(object sender, EventArgs e)
{
deg++;//let's rotate...
deg %= 360;//0...359
Invalidate(true);//queue for re-drawing
}
/// <summary>
/// custom painting for the Form ... called every time the form is re-drawn
/// </summary>
private void Form1_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
g.Clear(BackColor);
Point drawTo = new Point(Width / 2, Height / 2);//we want to draw the box in the center of the form
drawTo.Offset(-bmp.Width / 2, -bmp.Height / 2);//...but we need to specify the upper left corner
Point rotateAround = new Point(Width / 2, Height / 2);//we want to rotate the box around the center
g.TranslateTransform(-rotateAround.X, -rotateAround.Y); //translate the rotateAround point as 0,0
g.RotateTransform(-deg, System.Drawing.Drawing2D.MatrixOrder.Append);//rotate
g.TranslateTransform(rotateAround.X, rotateAround.Y, System.Drawing.Drawing2D.MatrixOrder.Append);//translate back
g.DrawImageUnscaled(bmp, drawTo);//draw the box with respect to current transforms...
g.ResetTransform();//now back to our original coordinate-space
var P = new Point(drawTo.X + p1.X, drawTo.Y + p1.Y); //the point we want to point to in the original coordinate-space (before rotation)
var O = rotateAround;
var rad = deg * Math.PI / 180d; //System.Math want's our angle in radians
//coordinate calculation for a rotation around O
//PT_x = (P_x - O_x) * cos(d) + (P_y - O_y) * sin(d) + O_x
//PT_y = -(P_x - O_x) * sin(d) + (P_y - O_y) * cos(d) + O_y
var PT_x = (P.X - O.X) * Math.Cos(rad) + (P.Y - O.Y) * Math.Sin(rad) + O.X;
var PT_y = -(P.X - O.X) * Math.Sin(rad) + (P.Y - O.Y) * Math.Cos(rad) + O.Y;
drawTo = new Point((int)PT_x, (int)PT_y);
g.DrawLine(Pens.Black, start, drawTo); // draw a line to the calculated point
}
//boiler plate code follows...
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.label1 = new System.Windows.Forms.Label();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(41, 43);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(197, 13);
this.label1.TabIndex = 1;
this.label1.Text = "Some fixed point to start drawing a line to the top left corner of a 'X' in a rotating box...";
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Timer timer1;
}
}