Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Drawing a grid for plotting a graph

Drawing a grid for plotting a graph

Scheduled Pinned Locked Moved C#
graphicsquestioncssdata-structures
6 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    Praveen Raghuvanshi
    wrote on last edited by
    #1

    Hi, I am plotting a graph between frequency on x-axis and gain on y-axis. X-axis(frequency) needs to vary logarithmically and y-axis(gain) needs to vary linearly. The first step was to create the axis and put numbers on the lines. As the default origin is at the Left Top corner of the client area, I moved the origin to the center of the client area and inverted the y-axis, so that whatever drawing takes place it should be as per the new origin and looks more realistic. I tried to create few lines along with string to number them. Lines are drawn properly, however the string also got inverted. Here is the code, I tried to use. It can be used in any winform application.

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
    Graphics g = e.Graphics;
    g.TranslateTransform(this.ClientSize.Width / 2, this.ClientSize.Height / 2);
    g.ScaleTransform(1, -1);

            Point A = new Point(0, 0);
            Point B = new Point(120, 80);
            Point C = new Point(120, -80);
    
            g.DrawLine(Pens.Red, A, B);
            g.DrawLine(Pens.Green, A, C);
    
            g.DrawLine(Pens.Purple, 0, 0, -50, 70);
            //g.ResetTransform();
            g.DrawString("3", new Font("Arial", 16), new SolidBrush(Color.Purple), B); 
        }
    

    Question 1: How can we draw string after inverting the y-axis? Question 2: How can we make vertical lines that should vary logarithmically? Any idea/solution is welcome.

    Praveen Raghuvanshi Software Developer

    L B 2 Replies Last reply
    0
    • P Praveen Raghuvanshi

      Hi, I am plotting a graph between frequency on x-axis and gain on y-axis. X-axis(frequency) needs to vary logarithmically and y-axis(gain) needs to vary linearly. The first step was to create the axis and put numbers on the lines. As the default origin is at the Left Top corner of the client area, I moved the origin to the center of the client area and inverted the y-axis, so that whatever drawing takes place it should be as per the new origin and looks more realistic. I tried to create few lines along with string to number them. Lines are drawn properly, however the string also got inverted. Here is the code, I tried to use. It can be used in any winform application.

      private void Form1_Paint(object sender, PaintEventArgs e)
      {
      Graphics g = e.Graphics;
      g.TranslateTransform(this.ClientSize.Width / 2, this.ClientSize.Height / 2);
      g.ScaleTransform(1, -1);

              Point A = new Point(0, 0);
              Point B = new Point(120, 80);
              Point C = new Point(120, -80);
      
              g.DrawLine(Pens.Red, A, B);
              g.DrawLine(Pens.Green, A, C);
      
              g.DrawLine(Pens.Purple, 0, 0, -50, 70);
              //g.ResetTransform();
              g.DrawString("3", new Font("Arial", 16), new SolidBrush(Color.Purple), B); 
          }
      

      Question 1: How can we draw string after inverting the y-axis? Question 2: How can we make vertical lines that should vary logarithmically? Any idea/solution is welcome.

      Praveen Raghuvanshi Software Developer

      L Offline
      L Offline
      lukeer
      wrote on last edited by
      #2

      Leave the graphics object untranslated and untransformed. Do the y-axis inversion and scaling in separate code instead. That way, you have full control over what is drawn where. A good idea would be to encapsulate all of that conversion processing so that you can call it using just "normal" values.

      Ciao, luker

      P 1 Reply Last reply
      0
      • L lukeer

        Leave the graphics object untranslated and untransformed. Do the y-axis inversion and scaling in separate code instead. That way, you have full control over what is drawn where. A good idea would be to encapsulate all of that conversion processing so that you can call it using just "normal" values.

        Ciao, luker

        P Offline
        P Offline
        Praveen Raghuvanshi
        wrote on last edited by
        #3

        Thanks Lukeer!!! I tried your suggestion, missed somewhere. Appreciate if you can help me draw three lines with numbering on them according to the order of drawing them. I wish to have origin in the center of the window and all points should be given according to that. Y-axis should be positive in the upward direction and negative in the downward direction. Thanks,

        Praveen Raghuvanshi Software Developer

        L 1 Reply Last reply
        0
        • P Praveen Raghuvanshi

          Hi, I am plotting a graph between frequency on x-axis and gain on y-axis. X-axis(frequency) needs to vary logarithmically and y-axis(gain) needs to vary linearly. The first step was to create the axis and put numbers on the lines. As the default origin is at the Left Top corner of the client area, I moved the origin to the center of the client area and inverted the y-axis, so that whatever drawing takes place it should be as per the new origin and looks more realistic. I tried to create few lines along with string to number them. Lines are drawn properly, however the string also got inverted. Here is the code, I tried to use. It can be used in any winform application.

          private void Form1_Paint(object sender, PaintEventArgs e)
          {
          Graphics g = e.Graphics;
          g.TranslateTransform(this.ClientSize.Width / 2, this.ClientSize.Height / 2);
          g.ScaleTransform(1, -1);

                  Point A = new Point(0, 0);
                  Point B = new Point(120, 80);
                  Point C = new Point(120, -80);
          
                  g.DrawLine(Pens.Red, A, B);
                  g.DrawLine(Pens.Green, A, C);
          
                  g.DrawLine(Pens.Purple, 0, 0, -50, 70);
                  //g.ResetTransform();
                  g.DrawString("3", new Font("Arial", 16), new SolidBrush(Color.Purple), B); 
              }
          

          Question 1: How can we draw string after inverting the y-axis? Question 2: How can we make vertical lines that should vary logarithmically? Any idea/solution is welcome.

          Praveen Raghuvanshi Software Developer

          B Offline
          B Offline
          BobJanova
          wrote on last edited by
          #4

          As Lukeer says, you should calculate the canvas position from chart coordinates yourself. Using translate and scale seems clever but as you've discovered it causes text to be drawn upside down as well. When I draw a log chart I still place gridlines linearly but label them logarithmically (e.g. 0.5, 1, 2, 4, or 1, 10, 100, 1000). I find the 'log graphpaper' approach to be fussy and generally not helpful. But if you want to do that then it is easy enough to calculate the appropriate chart coordinate Y values (log y at sensible Y values such as 1, 2, 5 each power of 10), and then you can transform those like all the other things for drawing.

          1 Reply Last reply
          0
          • P Praveen Raghuvanshi

            Thanks Lukeer!!! I tried your suggestion, missed somewhere. Appreciate if you can help me draw three lines with numbering on them according to the order of drawing them. I wish to have origin in the center of the window and all points should be given according to that. Y-axis should be positive in the upward direction and negative in the downward direction. Thanks,

            Praveen Raghuvanshi Software Developer

            L Offline
            L Offline
            lukeer
            wrote on last edited by
            #5

            Here is a quick proposal with horrible readablility:

                private PointF Transform(PointF logicalPoint)
                {
                    float logicalXMin = -100;
                    float logicalXMax = 100;
                    float logicalYMin = -100;
                    float logicalYMax = 100;
            
                    float canvasXMin = this.ClientRectangle.Left;
                    float canvasXMax = this.ClientRectangle.Right;
                    float canvasYMin = this.ClientRectangle.Top;
                    float canvasYMax = this.ClientRectangle.Bottom;
            
                    float canvasX = ((((float)(Math.Log(logicalPoint.X, 10))) - logicalXMin) / (logicalXMax - logicalXMin) \* (canvasXMax - canvasXMin)) + canvasXMin;
                    float canvasY = ((-logicalPoint.Y - logicalYMin ) / (logicalYMax - logicalYMin) \* (canvasYMax - canvasYMin)) + canvasYMin;
            
                    return (new PointF(canvasX, canvasY));
                }
            

            You use a control as canvas. You have to transform logical co-ordinates into canvas co-ordinates. Therefore you look at your logical value in relation to logical maximum and minimum. Then apply the same relation to canvas minimum and maximum. Since canvas Y-axis is inverted, you have to use negative logical Y value to compensate. As mathematics dictates, you can't use negative X values here. Draw grid lines using logical co-ordinates. They should get processed just as any data point.

            for( int power = 0, power < 4, power++)
            {
            g.DrawLine( gridPen, Math.Pow(1, power), logicalYMin, Math.Pow(1, power), logicalYMax);
            g.DrawLine( gridPen, Math.Pow(2, power), logicalYMin, Math.Pow(2, power), logicalYMax);
            g.DrawLine( gridPen, Math.Pow(5, power), logicalYMin, Math.Pow(5, power), logicalYMax);
            }

            Horizontal grid lines should be even easier.

            for( int i = logicalYMin; i <= logicalYMax; i += 10)
            {
            g.DrawLine( gridPen, logicalXMin, i, logicalXMax, i);
            }

            Ciao, luker

            modified on Wednesday, July 13, 2011 7:17 AM

            P 1 Reply Last reply
            0
            • L lukeer

              Here is a quick proposal with horrible readablility:

                  private PointF Transform(PointF logicalPoint)
                  {
                      float logicalXMin = -100;
                      float logicalXMax = 100;
                      float logicalYMin = -100;
                      float logicalYMax = 100;
              
                      float canvasXMin = this.ClientRectangle.Left;
                      float canvasXMax = this.ClientRectangle.Right;
                      float canvasYMin = this.ClientRectangle.Top;
                      float canvasYMax = this.ClientRectangle.Bottom;
              
                      float canvasX = ((((float)(Math.Log(logicalPoint.X, 10))) - logicalXMin) / (logicalXMax - logicalXMin) \* (canvasXMax - canvasXMin)) + canvasXMin;
                      float canvasY = ((-logicalPoint.Y - logicalYMin ) / (logicalYMax - logicalYMin) \* (canvasYMax - canvasYMin)) + canvasYMin;
              
                      return (new PointF(canvasX, canvasY));
                  }
              

              You use a control as canvas. You have to transform logical co-ordinates into canvas co-ordinates. Therefore you look at your logical value in relation to logical maximum and minimum. Then apply the same relation to canvas minimum and maximum. Since canvas Y-axis is inverted, you have to use negative logical Y value to compensate. As mathematics dictates, you can't use negative X values here. Draw grid lines using logical co-ordinates. They should get processed just as any data point.

              for( int power = 0, power < 4, power++)
              {
              g.DrawLine( gridPen, Math.Pow(1, power), logicalYMin, Math.Pow(1, power), logicalYMax);
              g.DrawLine( gridPen, Math.Pow(2, power), logicalYMin, Math.Pow(2, power), logicalYMax);
              g.DrawLine( gridPen, Math.Pow(5, power), logicalYMin, Math.Pow(5, power), logicalYMax);
              }

              Horizontal grid lines should be even easier.

              for( int i = logicalYMin; i <= logicalYMax; i += 10)
              {
              g.DrawLine( gridPen, logicalXMin, i, logicalXMax, i);
              }

              Ciao, luker

              modified on Wednesday, July 13, 2011 7:17 AM

              P Offline
              P Offline
              Praveen Raghuvanshi
              wrote on last edited by
              #6

              Thanks, I will give a shot.

              Praveen Raghuvanshi Software Developer

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups