如何在C#中计算旋转图像坐标?
我正在制作一个程序,通过使用x y坐标在picturebox中成像来画一些线。该图像将是可调整的,因此可以调整大小或旋转,但我希望绘制的线沿着图像,而不是停留在picturebox坐标。放大或缩小时,线条仍跟随图像,但旋转时,线条随机跳跃,不跟随图像 绘制了3条线的默认程序 线条仍在原位的缩放图像 将图像旋转10度。这些线跳转到随机位置 我现在用这个2个坐标组成一条线,但它使坐标到处随机跳跃,而不是随着图像旋转。 这是黑线1的代码 ---编辑--- 这是顺时针旋转的代码,但不知为什么它会逆时针移动。angle2值仍然未知,通过逆时针旋转,逐个尝试,32是可能的最接近位置。坐标没有像以前那样随机跳跃,现在它随图片旋转,但旋转的位置仍然不正确。将其旋转360度后,坐标位置将稍微偏离原始位置。每次旋转都是逆时针的 旋转前原稿,角度2为32 旋转360度后如何在C#中计算旋转图像坐标?,c#,rotation,coordinates,picturebox,C#,Rotation,Coordinates,Picturebox,我正在制作一个程序,通过使用x y坐标在picturebox中成像来画一些线。该图像将是可调整的,因此可以调整大小或旋转,但我希望绘制的线沿着图像,而不是停留在picturebox坐标。放大或缩小时,线条仍跟随图像,但旋转时,线条随机跳跃,不跟随图像 绘制了3条线的默认程序 线条仍在原位的缩放图像 将图像旋转10度。这些线跳转到随机位置 我现在用这个2个坐标组成一条线,但它使坐标到处随机跳跃,而不是随着图像旋转。 这是黑线1的代码 ---编辑--- 这是顺时针旋转的代码,但不知为什么它会逆
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;
逆时针旋转代码
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;
有人能告诉我如何修正这个旋转错误吗?多谢各位 您需要的是变换矩阵和偏移向量 p_x应为点p的x坐标,而p_y应为点p的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;
}
}
使用系统;
使用系统图;
使用System.Windows.Forms;
名称空间SoExamples.Rotation
{
公开课表格1:表格
{
位图bmp=新位图(100100);//占位符…我们的旋转框
点p1=新点(80,5);//旋转框中的一个点
int deg=0;//长方体的当前旋转角度,单位为0…359度
点开始;//开始绘制直线的点。。。
公共表格1()
{
初始化组件();
//准备我们的假盒子
使用(var graphics=graphics.FromImage(bmp))
{
graphics.Clear(Color.LightBlue);//背景色。。。
图形。抽绳(“X”,默认字体,画笔。白色,p1);
}
//正在计算直线的起点。。。
开始=新点(label1.Location.X+label1.Width/2,label1.Location.Y+label1.Height);//位于标签下方的中间
}
///
///计时器处理程序,每次调用计时器时执行…每100ms一次
///
私有无效计时器1_刻度(对象发送方,事件参数e)
{
deg++;//让我们旋转。。。
度%=360;//0…359
无效(true);//重新绘制的队列
}
///
///表单的自定义绘制…每次重新绘制表单时调用
///
私有void Form1_Paint(对象发送器、PaintEventArgs e)
{
var g=e.图形;
g、 清晰(背景色);
Point drawTo=新点(宽度/2,高度/2);//我们要在窗体的中心绘制框
drawTo.Offset(-bmp.Width/2,-bmp.Height/2);/…但我们需要指定左上角
Point rotateAround=新点(宽度/2,高度/2);//我们要围绕中心旋转长方体
g、 TranslateTransform(-rotateAround.X,-rotateAround.Y);//将rotateAround点转换为0,0
g、 RotateTransform(-deg,System.Drawing.Drawing2D.MatrixOrder.Append);//旋转
g、 TranslateTransform(rotateAround.X,rotateAround.Y,System.Drawing.Drawing2D.MatrixOrder.Append);//向后翻译
g、 DrawImageUnscaled(bmp,drawTo);//根据当前变换绘制框。。。
g、 ResetTransform();//现在回到原始坐标空间
var P=新点(drawTo.X+p1.X,drawTo.Y+p1.Y);//我们要在原始坐标空间中指向的点(旋转前)
var O=旋转周围;
var rad=deg*Math.PI/180d;//System.Math want是我们的角度,以弧度为单位
//绕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)*数学Cos(rad)+(P.Y-O.Y)*数学Sin(rad)+O.x;
变量PT_y=-(P.X-O.X)*数学Sin(rad)+(P.y-O.y)*数学Cos(rad)+O.y;
drawTo=新点((int)PT_x,(int)PT_y);
g、 DrawLine(Pens.Black,start,drawTo);//画一条到计算点的线
}
//锅炉板代码如下。。。
private System.ComponentModel.IContainer components=null;
受保护的覆盖无效处置(布尔处置)
{
if(处理和(组件!=null))
{
组件。Dispose();
}
基地。处置(处置);
}
私有void InitializeComponent()
{
this.components=new System.ComponentModel.Container();
this.label1=new System.Windows.Forms.Label();
this.timer1=新系统.Windows.Forms.Timer(this.components);
这个.SuspendLayout();
//
//标签1
//
this.label1.AutoSize=true;
this.label1.Location=新系统图纸点(41,43);
this.label1.Name=“label1”;
this.label1.Size=新系统。