Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Graphic transformations

Tags:

c#

graphics

I'm working with data (stuff like Sin/Cosin waves, etc) that repeat with frequency M. I've written a simple display control where it takes the data and paints connected lines to represent the data in a pretty picture.

My question is, the data is given where if painted onto a bitmap, quadrant 1 data is in quadrant 3 and quadrant 2 data is in quadrant 4 (and vice versa).

The bitmap is of width M and hight array.Max - array.Min.

Is there a simple transform for changing the data so it will display in the appropriate quadrants?

like image 603
joe_coolish Avatar asked Apr 27 '26 17:04

joe_coolish


2 Answers

A good way of thinking about it is that (0,0) in world coordinates is divided between

(0,0), (width, 0), (0,height), (width, height)

which would (width/2, height/2) in image coordinates.

From there, the transform would be:

Data(x,y) => x = ABS(x - (width/2)), y = ABS(y - (Height/2))
like image 58
joe_coolish Avatar answered Apr 29 '26 06:04

joe_coolish


Graphics.ScaleTransform is not a good idea because it will affect not only layout but also drawing itself (thickness of strokes, texts and so on).

I suggest you to prepare points list and then perform a transformation to them using the Matrix class. This is a small example I made for you, hope it will be helpful.

    private PointF[] sourcePoints = GenerateFunctionPoints();

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        e.Graphics.Clear(Color.Black);

        // Wee need to perform transformation on a copy of a points array.
        PointF[] points = (PointF[])sourcePoints.Clone();

        // The way to calculate width and height of our drawing.
        // Of course this operation may be performed outside this method for better performance.
        float drawingWidth = points.Max(p => p.X) - points.Min(p => p.X);
        float drawingHeight = points.Max(p => p.Y) - points.Min(p => p.Y);

        // Calculate the scale aspect we need to apply to points.
        float scaleAspect = Math.Min(ClientSize.Width / drawingWidth, ClientSize.Height / drawingHeight);

        // This matrix transofrmation allow us to scale and translate points so the (0,0) point will be
        // in the center of the screen. X and Y axis will be scaled to fit the drawing on the screen.
        // Also the Y axis will be inverted.
        Matrix matrix = new Matrix();
        matrix.Scale(scaleAspect, -scaleAspect);
        matrix.Translate(drawingWidth / 2, -drawingHeight / 2);

        // Perform a transformation and draw curve using out points.
        matrix.TransformPoints(points);
        e.Graphics.DrawCurve(Pens.Green, points);
    }

    private static PointF[] GenerateFunctionPoints()
    {
        List<PointF> result = new List<PointF>();

        for (double x = -Math.PI; x < Math.PI; x = x + 0.1)
        {
            double y = Math.Sin(x);
            result.Add(new PointF((float)x, (float)y));
        }

        return result.ToArray();
    }

    protected override void OnSizeChanged(EventArgs e)
    {
        base.OnSizeChanged(e);
        Invalidate();
    }
like image 39
Tom Kris Avatar answered Apr 29 '26 06:04

Tom Kris



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!