samedi 9 mai 2015

Rotate gauge needle in C# (WPF/.NET 4.5.1)

I cannot rotate the needle properly around its center without clipping occurring. The code I have found for rotation that doesn't result in clipping rotates the needle the wrong way. I found the code samples somewhere from stackoverflow.

Pic1 : correct position pointing south

Pic2 : RotateBitmap4(), rotation at wrong position, no clipping

Pic3 : RotateBitmap5(), correct rotation point but clipping

Pic4 : RotateBitmap5(), correct rotation point but clipping

Correct position Code snippet 1, rotation at wrong position, no clipping Code snippet 2, correct rotation point but clipping Code snippet 3, correct rotation point but clipping

        private void ButtonTestImage_OnClick(object sender, RoutedEventArgs e)
    {
        var backgroundImage = new Bitmap(TextBox1.Text);
        var foregroundImage = new Bitmap(TextBox2.Text);
        foregroundImage = ResizeBitmap(foregroundImage, 13, 65);

        //Wrong rotation, no clipping
        //foregroundImage = RotateBitmap4(foregroundImage, float.Parse(TextBoxAngle.Text));

        //Clipping!
        //foregroundImage = RotateBitmap5(foregroundImage, float.Parse(TextBoxAngle.Text));
        Console.WriteLine("foregroundImage width = " + foregroundImage.Width);
        Console.WriteLine("foregroundImage height = " + foregroundImage.Height);
        var finalImage = new Bitmap(320, 240);
        using (var graphics = Graphics.FromImage(finalImage))
        {
            //set background color
            graphics.Clear(System.Drawing.Color.Black);

            graphics.DrawImage(backgroundImage, new System.Drawing.Rectangle(0, 0, backgroundImage.Width, backgroundImage.Height));
            //graphics.DrawImage(foregroundImage, new System.Drawing.Rectangle(int.Parse(TextBoxXOffset.Text), int.Parse(TextBoxYOffset.Text), foregroundImage.Width, foregroundImage.Height));
            graphics.DrawImage(foregroundImage, new System.Drawing.Rectangle(int.Parse(TextBoxXOffset.Text), int.Parse(TextBoxYOffset.Text), foregroundImage.Width, foregroundImage.Height));
        }
        var image = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(finalImage.GetHbitmap(),IntPtr.Zero,System.Windows.Int32Rect.Empty,BitmapSizeOptions.FromWidthAndHeight(320, 240));
        ImageTest.Source = image;

        var newAngle = float.Parse(TextBoxAngle.Text) + 20;
        if (newAngle >= 360)
        {
            newAngle = 0;
        }
        TextBoxAngle.Text = (newAngle).ToString();
    }

    private Bitmap RotateBitmap5(Bitmap b, float angle)
    {
        //Create a new empty bitmap to hold rotated image.
        //Bitmap returnBitmap = new Bitmap(b.Width, b.Height);
        Bitmap returnBitmap = new Bitmap(b.Height+500, b.Height+500);
        //Make a graphics object from the empty bitmap.
        Graphics g = Graphics.FromImage(returnBitmap);
        //move rotation point to center of image.
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.TranslateTransform((float)b.Width / 2, (float)b.Height / 2);
        //Rotate.        
        g.RotateTransform(angle);
        //Move image back.
        g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2);
        //Draw passed in image onto graphics object.
        g.DrawImage(b, new System.Drawing.Point(0, 0));
        return returnBitmap;
    }

    public Bitmap RotateBitmap4(Bitmap b, float angle)
    {
        if (angle > 0)
        {
            int l = b.Width;
            int h = b.Height;
            double an = angle * Math.PI / 180;
            double cos = Math.Abs(Math.Cos(an));
            double sin = Math.Abs(Math.Sin(an));
            int nl = (int)(l * cos + h * sin);
            int nh = (int)(l * sin + h * cos);
            Bitmap returnBitmap = new Bitmap(nl, nh);
            Graphics g = Graphics.FromImage(returnBitmap);
            g.TranslateTransform((float)(nl - l) / 2, (float)(nh - h) / 2);
            g.TranslateTransform((float)b.Width / 2, (float)b.Height / 2);
            g.RotateTransform(angle);
            g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2);
            g.DrawImage(b, new System.Drawing.Point(0, 0));
            return returnBitmap;
        }
        else return b;
    }

Aucun commentaire:

Enregistrer un commentaire