Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中计算旋转图像坐标?_C#_Rotation_Coordinates_Picturebox - Fatal编程技术网

如何在C#中计算旋转图像坐标?

如何在C#中计算旋转图像坐标?,c#,rotation,coordinates,picturebox,C#,Rotation,Coordinates,Picturebox,我正在制作一个程序,通过使用x y坐标在picturebox中成像来画一些线。该图像将是可调整的,因此可以调整大小或旋转,但我希望绘制的线沿着图像,而不是停留在picturebox坐标。放大或缩小时,线条仍跟随图像,但旋转时,线条随机跳跃,不跟随图像 绘制了3条线的默认程序 线条仍在原位的缩放图像 将图像旋转10度。这些线跳转到随机位置 我现在用这个2个坐标组成一条线,但它使坐标到处随机跳跃,而不是随着图像旋转。 这是黑线1的代码 ---编辑--- 这是顺时针旋转的代码,但不知为什么它会逆

我正在制作一个程序,通过使用x y坐标在picturebox中成像来画一些线。该图像将是可调整的,因此可以调整大小或旋转,但我希望绘制的线沿着图像,而不是停留在picturebox坐标。放大或缩小时,线条仍跟随图像,但旋转时,线条随机跳跃,不跟随图像

绘制了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;
逆时针旋转代码

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=新系统。