Search code examples
c#matrixcoordinate-transformationrotational-matrices

C# rotation (transformation) issue


I'm trying to create program where will be List of fishes drawn on the canvas. (Next step will be changing the place of fishes based on some calculation) Each fish is represented by bitmap (png file 7x12 px with picture of fish).

I created Form on which is PictureBox which is my drawing canvas. It has size 640x480 px.

In code below is simplified code I use (I cutted off all not necesary stuff). My problem is with tranformation matrix, at the moment only with rotation.

Problem is in class Fish in method Draw() where I'm trying to make a tranformation, at the moment I set the rotation 30 degrees for each fish but later each fish will have different start rotation angle. I want to make a transformation with the where will the fish will be rotated by the rotation angle around its centre. So in this case all fishes should be in one line and rotated each by its rotation angle (here 30 degrees).
But they are placed on diagonale, so the transformation is messed up somehow. How can I fix this? I'm probably using tansformation incorectly.

Namespaces using in classes

using System.Drawing;//Graphics, Point
using System.Drawing.Drawing2D;//Matrix

Fish

    class Fish {
      public Point position;
      public int rotation;
      public Graphics g;
      public Image fishImage;
      private Rectangle rect;
      private Matrix matrix;

      public Fish(ref Graphics g, int x, int y, int rotation,Image img){
        this.g =  g;
        position = new Point(x,y);
        this.rotation = rotation;
        this.fishImage = img;
        this.rect = new Rectangle(position.X,position.Y, fishImage.Width, fishImage.Height);

      }

   public void Draw() {
    matrix = new Matrix();
    matrix.Rotate((float)rotation, Matrix.Append); //if i comment this it
    //will be drawn in one line
    //according to the initial values for position
    //if i let the rotation here it will be on diagonale
    //i want it on one line but rotated
    g.Transform = matrix;

    rect = new Rectangle(position.X, position.Y, fishImage.Width, fishImage.Height);
    g.DrawImage(fishImage, rect);
   }
}//end Fish class

Form

public partial class Form1 : Form
{
 private Bitmap canvasBitmap; //bitmap for drawing
 private Graphics g;          
 Image fishImage;

 private List<Fish> fishes = new List<Fish>();
  public Form1() {
    InitializeComponent();
   //png image 7x12 pixels 
   fishImage = FishGenetic.Properties.Resources.fishImage; 
   //on Form there is placed PictureBox called canvas
   //so canvas is PictureBox 640x480 px
   canvasBitmap = new Bitmap(canvas.Width, canvas.Height);
   canvas.Image = canvasBitmap;

   //prepare graphics
   g = Graphics.FromImage(canvasBitmap);
   g.SmoothingMode = SmoothingMode.AntiAlias;

   InitFishes();
   DrawFishes();
   canvas.Invalidate(); //invalidate the canvas 

  }//end Form1 constructor     


 private void InitFishes() {

   Fish fish1 = new Fish(ref g, 10, 10, 30, fishImage);
   Fish fish2 = new Fish(ref g, 20, 10, 30, fishImage);
   Fish fish3 = new Fish(ref g, 30, 10, 30, fishImage);
   Fish fish4 = new Fish(ref g, 40, 10, 30, fishImage);
   Fish fish5 = new Fish(ref g, 50, 10, 30, fishImage);
   fishes.Add(fish1);
   fishes.Add(fish2);
   fishes.Add(fish3);
   fishes.Add(fish4);
   fishes.Add(fish5);
 }

private void DrawFishes() {
   foreach(Fish fish in fishes) {
       fish.Draw();
   }
}

}//end Form1 class

Main class

static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

Solution

  • You should use RotateAt instead of Rotate. Rotate method rotates the fish around the upper left corner of the control (origin) while RotateAt rotates something around a point specified by you.

    Just calculate the center of each fish (X=Left+FishWidth/2, Y=Top+FishHeight/2) and rotate around that point.