2013-07-11 44 views
1

下面是一张图片,说明我正在尝试做什么。找到旋转后的图像内的原始点c#

http://tinypic.com/r/nvbehh/5

我旋转在c#的图像(白色矩形)。 问题是我需要将绿色正方形(另一个图像)放在与矩形相同的点上,而不管旋转。绿色正方形不能与矩形一起旋转。

正如你可以看到在白色矩形旋转后,我每次都会得到不同大小的画布。

我想找到确切的点来放置新的旋转图像创建后的绿色广场。

以下OK是一些代码,它旋转图像并将点放在正确的位置。 现在的问题是,如果我在RotateImage方法中应用转换,我会看到所有的rectagle,但显然我的红点在错误的位置。 我应该强调,我需要知道点的位置,而不是将它放在正确的位置。

public class IconController : Controller 
{ 
    // 
    // GET: /Icon/ 

    public ActionResult Index() 
    { 
     return View(); 
    } 

    ////Icon/Icon?connected=true&heading=320&type=logo45 
    public ActionResult Icon(bool connected, float heading, string type) 
    { 
     var dir = Server.MapPath("/images"); 
     //RED SQUARE IM TRYING TO PLACE ON THE BLUE RECTANGLE. 
     var path = Path.Combine(dir, "mapicons/center.png"); 

     //GREEN RECTANGLE WITH FIXED YELLOW (Actual center) AND BLUE (point im really trying to find) 
     var path2 = Path.Combine(dir, "mapicons/connected-marker.png"); 

     Image innerIcon = Image.FromFile(path); 
     Image marker = Image.FromFile(path2); 

     using (marker) 
     { 

      Point orginalCenter = new Point((marker.Width/2), (marker.Height/2)); 
      Bitmap markerbitmap = RotateImage(new Bitmap(marker), heading); 

      marker = (Image)markerbitmap; 
      using (var bitmap = new Bitmap(marker.Width, marker.Height)) 
      { 
       using (var canvas = Graphics.FromImage(bitmap)) 
       { 
        PointF newCenter = RotatePoint(orginalCenter, 80, 120, heading, marker.Width, marker.Height); 
        canvas.DrawRectangle(new Pen(Color.Black), 0, 0, bitmap.Width, bitmap.Height); 
        canvas.InterpolationMode = InterpolationMode.HighQualityBicubic; 
        canvas.DrawImage(marker, new Rectangle(0, 0, marker.Width, marker.Height), new Rectangle(0, 0, marker.Width, marker.Height), GraphicsUnit.Pixel); 
        canvas.DrawImage(innerIcon, newCenter.X - (innerIcon.Width/2), newCenter.Y - (innerIcon.Height/2)); 

        canvas.Save(); 
       } 
       try 
       { 
        bitmap.Save(Path.Combine(dir, "result.png"), ImageFormat.Png); 
        path = Path.Combine(dir, "result.png"); 
       } 
       catch (Exception ex) { } 
      } 
     } 


     return base.File(path, "image/png"); 
    } 

    public static Bitmap RotateImage(Bitmap b, float Angle) 
    { 
     // The original bitmap needs to be drawn onto a new bitmap which will probably be bigger 
     // because the corners of the original will move outside the original rectangle. 
     // An easy way (OK slightly 'brute force') is to calculate the new bounding box is to calculate the positions of the 
     // corners after rotation and get the difference between the maximum and minimum x and y coordinates. 
     float wOver2 = b.Width/2.0F; 
     float hOver2 = b.Height/2.0F; 
     float radians = -(float)(Angle/180.0 * Math.PI); 
     // Get the coordinates of the corners, taking the origin to be the centre of the bitmap. 
     PointF[] corners = new PointF[]{ 
     new PointF(-wOver2, -hOver2), 
     new PointF(+wOver2, -hOver2), 
     new PointF(+wOver2, +hOver2), 
     new PointF(-wOver2, +hOver2) 
     }; 

     for (int i = 0; i < 4; i++) 
     { 
      PointF p = corners[i]; 
      PointF newP = new PointF((float)(p.X * Math.Cos(radians) - p.Y * Math.Sin(radians)), (float)(p.X * Math.Sin(radians) + p.Y * Math.Cos(radians))); 
      corners[i] = newP; 
     } 

     // Find the min and max x and y coordinates. 
     float minX = corners[0].X; 
     float maxX = minX; 
     float minY = corners[0].Y; 
     float maxY = minY; 
     for (int i = 1; i < 4; i++) 
     { 
      PointF p = corners[i]; 
      minX = Math.Min(minX, p.X); 
      maxX = Math.Max(maxX, p.X); 
      minY = Math.Min(minY, p.Y); 
      maxY = Math.Max(maxY, p.Y); 
     } 

     // Get the size of the new bitmap. 
     SizeF newSize = new SizeF(maxX - minX, maxY - minY); 
     // ...and create it. 
     Bitmap returnBitmap = new Bitmap((int)Math.Ceiling(newSize.Width), (int)Math.Ceiling(newSize.Height)); 
     // Now draw the old bitmap on it. 
     using (Graphics g = Graphics.FromImage(returnBitmap)) 
     { 
      g.TranslateTransform(newSize.Width/2.0f, newSize.Height/2.0f); 
      g.RotateTransform(Angle); 

     g.TranslateTransform(-b.Width/2.0f, -b.Height/2.0f); 

      g.DrawImage(b, 0, 0); 
     } 

     return returnBitmap; 
    } 


    public 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); 

     Point pt = new Point(); 
     pt.X = (int)(cosTheta * (pointToRotate.X-centerPoint.X) - sinTheta * (pointToRotate.Y-centerPoint.Y) + centerPoint.X); 

     pt.Y = (int)(sinTheta * (pointToRotate.X - centerPoint.X) + cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y); 
     //p'y = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy 

     return pt; 

    } 
} 

所以现在我需要能够取消对TranslateTransform在RotateImage方法,让我看到了正确的矩形和修改RotatePoint方法,所以我得到正确的新位置

+0

你需要做数学题,即旋转相匹配。也许谷歌“旋转矩形算法”。您正在寻找给定4个角的XY位置的数学,应用旋转。我强调你正在寻找MATH,而不是调用GUI。使用Sin()和Cos()的东西。那么你需要弄清楚这与你的视觉形象有何关系。 – ToolmakerSteve

+0

OK上面确实打算。 @ToolmakerSteve谢谢你指点我正确的方向。不知道如何标记为答案等 – Ray

+0

很高兴这有帮助。你可以为自己的问题写一个答案(“回答你的问题”按钮),并鼓励他们这样做,这样人们就知道它已经得到了回答。然后将其标记为答案。如果您在问题中已经更正了这个问题,那么您可能会在回答中显示“之前”和“之后”,以表明您最初失踪的内容。 – ToolmakerSteve

回答

0

这里是工作控制器。
公共类IconController:控制器 {// // GET:/图标/

public ActionResult Index() 
    { 
     return View(); 
    } 

    ////Icon/Icon?connected=true&heading=320&type=logo45 
    public ActionResult Icon(bool connected, float heading, string type) 
    { 
     var dir = Server.MapPath("/images"); 
     //RED SQUARE IM TRYING TO PLACE ON THE BLUE RECTANGLE. 
     var path = Path.Combine(dir, "mapicons/center.png"); 

     //GREEN RECTANGLE WITH FIXED YELLOW (Actual center) AND BLUE (point im really trying to find) 
     var path2 = Path.Combine(dir, "mapicons/connected-marker.png"); 

     Image innerIcon = Image.FromFile(path); 
     Image marker = Image.FromFile(path2); 

     using (marker) 
     { 

      Point orginalCenter = new Point((marker.Width/2), (marker.Height/2)); 
      Bitmap markerbitmap = RotateImage(new Bitmap(marker), heading); 

      marker = (Image)markerbitmap; 
      using (var bitmap = new Bitmap(marker.Width, marker.Height)) 
      { 
       using (var canvas = Graphics.FromImage(bitmap)) 
       { 
        PointF newCenter = RotatePoint(orginalCenter, 80, 120, heading, marker.Width, marker.Height); 
        canvas.DrawRectangle(new Pen(Color.Black), 0, 0, bitmap.Width, bitmap.Height); 
        canvas.InterpolationMode = InterpolationMode.HighQualityBicubic; 
        canvas.DrawImage(marker, new Rectangle(0, 0, marker.Width, marker.Height), new Rectangle(0, 0, marker.Width, marker.Height), GraphicsUnit.Pixel); 
        canvas.DrawImage(innerIcon, newCenter.X - (innerIcon.Width/2), newCenter.Y - (innerIcon.Height/2)); 

        canvas.Save(); 
       } 
       try 
       { 
        bitmap.Save(Path.Combine(dir, "result.png"), ImageFormat.Png); 
        path = Path.Combine(dir, "result.png"); 
       } 
       catch (Exception ex) { } 
      } 
     } 


     return base.File(path, "image/png"); 
    } 

    public static Bitmap RotateImage(Bitmap b, float Angle) 
    { 
     // The original bitmap needs to be drawn onto a new bitmap which will probably be bigger 
     // because the corners of the original will move outside the original rectangle. 
     // An easy way (OK slightly 'brute force') is to calculate the new bounding box is to calculate the positions of the 
     // corners after rotation and get the difference between the maximum and minimum x and y coordinates. 
     float wOver2 = b.Width/2.0F; 
     float hOver2 = b.Height/2.0F; 
     float radians = -(float)(Angle/180.0 * Math.PI); 
     // Get the coordinates of the corners, taking the origin to be the centre of the bitmap. 
     PointF[] corners = new PointF[]{ 
     new PointF(-wOver2, -hOver2), 
     new PointF(+wOver2, -hOver2), 
     new PointF(+wOver2, +hOver2), 
     new PointF(-wOver2, +hOver2) 
     }; 

     for (int i = 0; i < 4; i++) 
     { 
      PointF p = corners[i]; 
      PointF newP = new PointF((float)(p.X * Math.Cos(radians) - p.Y * Math.Sin(radians)), (float)(p.X * Math.Sin(radians) + p.Y * Math.Cos(radians))); 
      corners[i] = newP; 
     } 

     // Find the min and max x and y coordinates. 
     float minX = corners[0].X; 
     float maxX = minX; 
     float minY = corners[0].Y; 
     float maxY = minY; 
     for (int i = 1; i < 4; i++) 
     { 
      PointF p = corners[i]; 
      minX = Math.Min(minX, p.X); 
      maxX = Math.Max(maxX, p.X); 
      minY = Math.Min(minY, p.Y); 
      maxY = Math.Max(maxY, p.Y); 
     } 

     // Get the size of the new bitmap. 
     SizeF newSize = new SizeF(maxX - minX, maxY - minY); 
     // ...and create it. 
     Bitmap returnBitmap = new Bitmap((int)Math.Ceiling(newSize.Width), (int)Math.Ceiling(newSize.Height)); 
     // Now draw the old bitmap on it. 
     using (Graphics g = Graphics.FromImage(returnBitmap)) 
     { 
      g.TranslateTransform(newSize.Width/2.0f, newSize.Height/2.0f); 
      g.RotateTransform(Angle); 

     g.TranslateTransform(-b.Width/2.0f, -b.Height/2.0f); 

      g.DrawImage(b, 0, 0); 
     } 

     return returnBitmap; 
    } 


    public 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); 

     Point pt = new Point(); 
     pt.X = (int)(cosTheta * (pointToRotate.X-centerPoint.X) - sinTheta * (pointToRotate.Y-centerPoint.Y) + centerPoint.X); 

     pt.Y = (int)(sinTheta * (pointToRotate.X - centerPoint.X) + cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y); 
     //p'y = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy 

     return pt; 

    } 
}