Plot graph

edited November 2016 in How To...

I need some way to plot a graph in Processing. I just need it for a simple quadratic equation. I found this tool: http://www.gwoptics.org/processing/gwoptics_p5lib/ via this thread https://processing.org/discourse/beta/num_1270229678.html However it seems like the gwoptics library is not supported in Processing 3. Any suggestions of alternatives I can use?

Answers

  • Try this other link as well:

    https://forum.processing.org/two/discussion/comment/70182/#Comment_70182

    Also you should check the gicentreUtils lib (Add library using the Processing IDE). Also the grafica library, which I think it would be more relevant to your needs.

    Kf

  • edited November 2016

    @keykeeper -- as @kfrajer mentions, for axes, labels, etc., you could try the giCentre Utils "Chart".

    For graphing a quadratic function in Processing - you could just implement the quadratic function as a Processing function to solve y for any x given a b c:

    // general quadratic function: y = ax^2 + bx + c
    float quadraticY (float a, float b, float c, float x){
      return (a*x*x + b*x + c);
    }    
    

    If you want to graph a parabola in a given range, generate a list of points by looping over the range xmin to xmax, and draw point(x, quadraticY(x)) of the parabola, e.g.:

    void quadraticPoints (float a, float b, float c, float xmin, float xmax){
      float y;
      for(float x=xmin; x<xmax; x=x+0.25){
        y = a*x*x + b*x + c;
        point(x, y);
      }
    }
    

    You can:

    1. plot them directly as point()s
    2. or use them to draw a connected line segment approximation
    3. add each to a PShape as vertex
    4. or store them as a PVector[] array

    QuadraticDots

  • You might try the graphica library

  • Thank you all for input on this. I imported both gicentreUtils and grafica and tested all the examples but none of them seems to provide me with a simple solution for plotting the graph for 3(xx)+2x-1=0

    jeremydouglass - the screenshot you provided seems like what I am after, but can I please ask you to provide the complete code for generating this graph?

  • Take my link

  • @keykeeper

    if you post your code, we can make either grafica or gicentreUtils work. Or you can use @Chrisir's link as it is close to what @jeremydouglass presented.

    Kf

  • // the max x for our test
    int maxX = 200;
    
    // ---------------------------------------------------------------
    
    void setup() {
      // init
      size(900, 600);
    
      background(111);
    
      drawCoordSystem(); 
    
      // draw graph 
      for (int x=-maxX; x < maxX; x++) {
        // formula: 
        float y =  x*x * .019;
        // apply to screen coordinate system
        PVector getScreenCoords = matchToScreenCoordinates(x, y); 
        // draw point 
        pointPVector(getScreenCoords);
      }
    } // func 
    
    void draw() { 
    
      // text box upper left corner 
      fill(111);
      noStroke();
      rect (0, 0, 100, 100);
      fill(255);
      text(" Plot Graph.", 30, 30);
    } // func 
    
    void drawCoordSystem() {
    
      // draw coord system in white 
      // (apply to screen coordinate system) 
      PVector getScreenCoord1 = matchToScreenCoordinates(-maxX, 0);
      PVector getScreenCoord2 = matchToScreenCoordinates(maxX, 0);
      linePVectors(getScreenCoord1, getScreenCoord2);
    
      getScreenCoord1 = matchToScreenCoordinates(0, 0);
      getScreenCoord2 = matchToScreenCoordinates(0, 333);
      linePVectors(getScreenCoord1, getScreenCoord2);
    }
    
    PVector matchToScreenCoordinates (float x, float y) {
      // apply to screen coordinate system
      return new PVector (x+450, height-y-10);
    }
    
    void pointPVector(PVector pv) {
      // draw point at pv
      stroke(255, 2, 2); // red 
      point(pv.x, pv.y);
    }
    
    void linePVectors(PVector pv1, PVector pv2) {
      // draw line from pv1 to pv2
      stroke(255); // white 
      line(pv1.x, pv1.y, 
        pv2.x, pv2.y);
    } 
    
    //
    
  • edited November 2016

    https://www.google.de/search?q=x*x

    for processing we have to write it with * : 3*(x*x)+2*x-1=0

    Google can't do this.

    check wolfram alpha

  • new version with your formula and improved scaling

    // the max x for our test
    int maxX = 100; // (in neg and pos direction)
    
    // ---------------------------------------------------------------
    
    void setup() {
      // init
      size(900, 600);
      background(111);
    
      drawCoordSystem(); 
    
    
      // draw graph
      float y; 
      for (float x=-maxX; x < maxX; x+=.01) {
        // formulas: 
        // y =  x*x;
        y  = (3*(x*x))+(2*x)-1; 
        // apply to screen coordinate system
        PVector getScreenCoords = matchToScreenCoordinates(x, y); 
        // draw point 
        pointPVector(getScreenCoords);
      }//for
    } // func 
    
    void draw() { 
    
      // text box upper left corner 
      fill(111);
      noStroke();
      rect (0, 0, 100, 100);
      fill(255);
      text(" Plot Graph.", 30, 30);
    } // func 
    
    // ---------------------------------------------------------------
    
    void drawCoordSystem() {
    
      // draw coord system in white 
    
      // (apply to screen coordinate system) 
      PVector getScreenCoord1 = matchToScreenCoordinates(-maxX, 0);
      PVector getScreenCoord2 = matchToScreenCoordinates(maxX, 0);
      linePVectors(getScreenCoord1, getScreenCoord2);
    
      getScreenCoord1 = matchToScreenCoordinates(0, height);
      getScreenCoord2 = matchToScreenCoordinates(0, -height);
      linePVectors(getScreenCoord1, getScreenCoord2);
    
      for (int x = -10; x<10; x++) {
        getScreenCoord1 = matchToScreenCoordinates(x, -.3);
        getScreenCoord2 = matchToScreenCoordinates(x, .3);
        linePVectors(getScreenCoord1, getScreenCoord2);
      }//for
    
      for (int y = -10; y<10; y++) {
        getScreenCoord1 = matchToScreenCoordinates( -.3, y);
        getScreenCoord2 = matchToScreenCoordinates( .3, y);
        linePVectors(getScreenCoord1, getScreenCoord2);
      }//for
    }//func 
    
    // -------------------------------------------------------------------
    // convert the data from formula to screen appropriate format
    
    PVector matchToScreenCoordinates (float x, float y) {
      // convert to screen coordinate system
    
      x*=40.0;
      y*=40.0;  //y=y*0.019; 
      return new PVector (x+width/2, height/2-y-30);
    }
    
    // -------------------------------------------------------------------
    // PVector functions 
    
    void pointPVector(PVector pv) {
      // draw point at pv
      stroke(255, 2, 2); // red 
      point(pv.x, pv.y);
    }
    
    void linePVectors(PVector pv1, PVector pv2) {
      // draw line from pv1 to pv2
      stroke(255); // white 
      line(pv1.x, pv1.y, 
        pv2.x, pv2.y);
    } 
    
    //
    
  • edited November 2016

    @keykeeper -- here is a simple demo that draws the x and y axis, centers drawing on the axis, and then renders a quadratic equation with points. It created the image in the thread above.

    /**
     * Quadratic Points
     * plot a quadratic equation with points
     * 2016-11-20
     * Jeremy Douglass
     * Processing 3.2.3
     * forum.processing.org/two/discussion/19180/plot-graph
     */
    
    PVector origin;
    
    void setup(){
      size(400,400);
      origin = new PVector(width/2, 3*height/4);
    }
    
    void draw(){
      // draw axes (relative to screen edges)
      stroke(255,0,0);
      line(0,origin.y,width,origin.y);
      line(origin.x,0,origin.x,height);
    
      // draw graph -- center on origin, y goes up not down
      translate(origin.x, origin.y);
      scale(1, -1);
      stroke(0);
    
      // draw quadratic function with points
      quadraticPoints(0.025, 2, 30, -width/2, width/2);
    }
    
    void quadraticPoints (float a, float b, float c, float xmin, float xmax){
      float y;
      for(float x=xmin; x<xmax; x=x+0.25){
        y = a*x*x + b*x + c; // ( y = 0.025x^2 + 2x + 30 )
        point(x, y);
      }
    }
    
  • P.S. I believe that there is also an alternate approach which uses the built in curve functions and is much more concise. However, it is a bit tricky.

    You can describe a segment of quadratic equation parabola using only a pair of endpoints -- one a single vertex, one a single quadraticVertex. However, getting the correct parabola requires you to calculate the single quadraticVertex control point correctly, which lies at the midpoint but beyond the parabola vertex.

  • Thank you all for the input on this. It has been really helpful.

    I just have two follow ups: Chrisir - In the method matchToScreenCoordinates x and y is multiplied with 40. Why 40?

    jeremydouglass-I tried your code sending in a=3 b=2,c=-1 but the graph did not cross the x axis. Is there anything else I need to adjust?

  • The 40 is just the scaling from the data to what you see on the screen

    40 just looked ok, no deeper reason

  • edited November 2016

    @keykeeper -- looks like there was an error in this line:

    translate(origin.x, origin.y - 10);
    

    Should be:

    translate(origin.x, origin.y);
    

    That was a quick demo -- if you want labeled axes etc. etc. then the draw loop needs to be redone.

    You also want to base your function on units, not pixels on. I cheated and just made a = 0.025 to avoid the incredibly steep curve that you get on a 400-wide graph. Instead compute actual points and then map them to pixel space with a scaling factor.

  • edited November 2016

    @keykeeper -- if you want nicely labeled and formatted graphs with good presentation, your best bet is probably to:

    1. implement the quadratic equation as a function as in my example (y = a*x*x + b*x + c;),
    2. save the output to a list of points
    3. render those points using the grafica library -- e.g. load those points into something like the default plot example.

    If instead you want to learn how to create graphs or how customize your own from scratch, then both @Chrisir and my examples each demonstrate some of the basic logic of setting up graph display (axes, scaling, etc.). I've updated my example to show axis units, to make the function display-independent, and to display both the "points" (black) and the "PShape" (blue) method of rendering the same curve.

    /**
     * Quadratic Points and Shapes
     * plot a quadratic equation with points and shapes
     * 2016-11-23
     * Jeremy Douglass
     * Processing 3.2.3
     * forum.processing.org/two/discussion/19180/plot-graph
     */
    
    PVector origin;
    ArrayList<PVector> curve;
    PShape curveshape;
    int scale;
    int tick;
    
    void setup(){
      size(400,400,P2D);
      origin = new PVector(width/2, 5*height/8);
      scale = 20;
      tick = 3;
      // compute points for curve (APPROACH 1)
      curve = quadraticPoints(0.2, 0, -2, -width/2, width/2);
    
      // load points into PShape (APPROACH 1+2)
      curveshape = createShape();
      curveshape.beginShape();
      curveshape.fill(0,0);
      curveshape.stroke(0,0,255);
      curveshape.strokeWeight(2);
      for(PVector v : curve){
        curveshape.vertex(v.x * scale, v.y * scale);
      }
      curveshape.endShape();
    }
    
    void draw(){
      background(239);
      // draw graph -- center on origin, y goes up not down
      translate(origin.x, origin.y);
      scale(1, -1);
    
      stroke(255,0,0);
      strokeWeight(2);
    
    
      // draw axes
      line(-origin.x,0,origin.x,0);
      line(0,origin.y,0,-origin.y);
    
      // draw axis ticks
      for(int x=0; x<origin.x; x=x+scale){
        line( x,  tick,  x, -tick);
        line(-x,  tick, -x, -tick);
      }
      for(int y=0; y<origin.y; y=y+scale){
        line( tick,  y, -tick,  y);
        line( tick, -y, -tick, -y);
      }
    
      stroke(0);
    
      // draw points or shape curve
      if(second()%2==0){
        // draw from points list (APPROACH 1)
        for(PVector v : curve){
          point(v.x * scale, v.y * scale);
        }
      } else {
        // draw from curve PShape (APPROACH 1+2)
        shape(curveshape);
      }
    }
    
    ArrayList<PVector> quadraticPoints (float a, float b, float c, float xmin, float xmax){
      float y;
      ArrayList<PVector> pvlist = new ArrayList<PVector>();
      for(float x=xmin; x<xmax; x=x+0.05){
        y = a*x*x + b*x + c;
        // point(x*scale, y*scale);
        pvlist.add(new PVector(x,y));
      }
      return(pvlist);
    }
    

    QuadraticPointsAndShapes

  • A final note on the points vs. shape approaches:

    Note that the "points" method is simple, but needs really high resolution -- e.g. maybe 4+ points drawn on the curve for every 1 pixel of x-width -- it will look sparse / disconnected at low point sample rates -- or even at high rates where the slope is steepest.

    QuadraticPointsAndShapes2

    By contrast contrast, PShape doesn't need as many points, and will always look connected -- however at very low plotting resolution drops, it will start to look angular / jagged.

    QuadraticPointsAndShapes3

  • Thank you again for the advise. It has been very good to get insight on how to create graphs in Processing.

Sign In or Register to comment.