2D Data Plotting

Posted on March 4th, 2014
Previous Article :: Next Article

To demonstrate the scalar to RGB colormap from the previous article, I put together a little demo showing how to visualize some 2D scalar field. Here I am plotting \(f(x,y)=1-0.5(x^2+y^2)\). This function varies radially from 1 at the origin to 0 in the corners of \([-1,-1]:[1,1]\) domain. Ideally, you would want to visualize the results by performing contouring. But in the absence of an actual contouring algorithm (the Visualization Toolkit book is a great reference) we obtain insight into the data by flooding each computational cell with the cell primary value. You can use the sliders below the change the numbers of levels and the cell spacing.

Your browser does not support canvas
Contours:
ni:
nj:

Source Code

You can see the entire source code by opening the following link and using “Right click -> view source”. As you can see, the entire code is only 80 lines long. We first specify the needed HTML elements, mainly <canvas> and <form>:

<div style="padding-left: 2em;text-align:left">
<canvas id="canvas" width="400" height="400" style="border: 2px solid black;margin-bottom: 0.25em;">
Your browser does not support canvas
</canvas>
 
<form action="null" method="post">
Contours: <input type="range" id="nc" min="1" max="250" value="25" oninput="replot();" ><span id="span_nc"></span><br>
ni: <input type="range" id="ni" min="5" max="80" value="40" style="width:100px" oninput="replot();" ><span id="span_ni"></span><br> 
nj: <input type="range" id="nj" min="5" max="80" value="40" style="width:100px" oninput="replot();" ><span id="span_nj"></span><br>
</form>
</div>

As you can see, whenever one of the inputs changes, we call function replot(). We also definite another function, called init() which is called just once to set up the transformation.

<script>
init();
replot();
 
/*uses form data to regenerate the plot*/
function replot()
{
    var nc=document.getElementById("nc").value;
    var ni=document.getElementById("ni").value;
    var nj=document.getElementById("nj").value;
 
    document.getElementById("span_nc").innerHTML="("+nc+")";
    document.getElementById("span_ni").innerHTML="("+ni+")";
    document.getElementById("span_nj").innerHTML="("+nj+")";
 
    plot(ni,nj,nc);
}
 
var ctx;
/*gets context and sets transformation*/
function init()
{
    var c = document.getElementById("canvas");
    ctx = c.getContext("2d");
    var w=c.width;
    var h=c.height;
    /*transform to set canvas range from (-1,-1) in bottom left to (1,1) in top right*/ 
    ctx.translate(0.5*w,0.5*h);
    ctx.scale(0.5*w,-0.5*h);
    ctx.lineWidth=2/w;
}

Finally, the actual plotting is done in the function plot(). This function takes as its inputs the number of cells in the x and y direction, as well as the number of banded levels. For each cell, ranging from (x,y) to (x+di,y+dj), we compute the function $latex f=1-0.5(x_c^2+y_c^2)$ at the cell centroid. The color is converted to a banded value using b = Math.round(z*nlev)/nlev. This scalar is then converted to RGB using the method described in the previous article, Converting Scalars to RGB. The color is used to “flood” the cell, by painting a solid filled rectangle. You may notice that the width of the rectangle is slightly larger than di and dj. This is done to overlap the rectangles, to avoid gaps. The code is again below.

/*plots a scalar function f=1-0.5(x^2+y^2) on domain (-1,-1):(1,1)*/
function plot(ni,nj,nlev)
{
  ctx.strokeRect(-1,-1,2,2);	//add border
  var di = 2/(ni-1);			//cell spacing, total length=2
  var dj = 2/(nj-1);
  var x0 = -1;
  var y0 = -1;
 
  for (var j=0;j<nj;j++)
    for (var i=0;i<ni;i++)
    {
      var x = x0+i*di;	//this is the origin of the cell
      var y = y0+j*dj;
 
      var xc = x+0.5*di;	 //this is the centroid of the cell
      var yc = y+0.5*dj;
 
      var z = 1-0.5*(xc*xc+yc*yc);	//evaluate at the centroid
      var b = Math.round(z*nlev)/nlev; //banded value
 
      var a=(1-b)/0.25;		//invert and group
      var X=Math.floor(a);	//this is the integer part
      var Y=Math.floor(255*(a-X)); //fractional part from 0 to 255
      switch(X)
      {
        case 0: r=255;g=Y;b=0;break;
	case 1: r=255-Y;g=255;b=0;break;
	case 2: r=0;g=255;b=Y;break;
	case 3: r=0;g=255-Y;b=255;break;
	case 4: r=0;g=0;b=255;break;
      }
 
      ctx.fillStyle = "rgb("+r+","+g+","+b+")";
      ctx.fillRect(x,y,di*1.2,dj*1.2); //1.2x to avoid gaps
    }
}

2 comments to “2D Data Plotting”

  1. zguir
    April 21, 2014 at 8:05 pm

    Bonjour j ai un petit problème au niveau de simulation de l equation de la place en 2 dimension je trouve que la solution u du système linéaire est constante et quand je calcul l inverse de la matrice j ai la meme valeur qui se repete sachant que je travail avec la méthode des éléments finis et les condition au limite u=0 j ai besoin de votre aide merci d avance

  2. kslash
    June 8, 2014 at 10:29 pm

    –zguir

    I managed to understand you have problems solving 2d laplace heat eq (?) at the step where you solve the system of linear eqs. I would recommend to research the TDMA line-by-line solving and its application to 2d domains.

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="" escaped="" cssfile=""> In addition, you can use \( ...\) to include equations.