Question

This is my attempt to simulate the water surface. It works fine when I use the surf() function. But when I change it to bar3(), this error occurs: "Matrix dimensions must agree, not rendering mesh". Can some one please tell me how to fix this? Here's my code:

      n=60;
      i = 2:n-1;
      j = 2:n-1;
      H = ones(n,n);

      Dropx=30; %x and y coordinate of the droplet
      Dropy=30;
      width=20;
      r=width/2;
      dt=0.1;
      dx=0.3;

      %%% add droplet to the surface %%%
      [x,y] = ndgrid(-1.5:(2/(width/1.5-1)):1);
      D = 8*exp(-5*(x.^2+y.^2));
      w = size(D,1);
      i2 = (Dropx-r):w+(Dropx-r)-1;
      j2 = (Dropy-r):w+(Dropy-r)-1;
      H(i2,j2) = H(i2,j2) + D;

      oldH=H;
      newH=H;
      h=surf(newH); % cannot change this to bar3
      axis([1 n 1 n -2 8]);
      k=0.2; %damping constant
      c=2;   %wave speed

      while 1==1
          newH(i,j)=H(i,j)+(1-k*dt)*(H(i,j)-oldH(i,j))-...
          dt^2*c^2/dx^2*((4*H(i,j)-H(i+1,j)-H(i-1,j)-H(i,j+1)-H(i,j-1))...
          +0.4*(4*H(i,j)-H(i+1,j+1)-H(i+1,j-1)-H(i-1,j+1)-H(i-1,j-1)));
          set(h,'Zdata', newH(i,j));
          oldH=H;
          H=newH;
          pause(0.05);
      end
Was it helpful?

Solution

The problem, as stated by David, is that bar3 transforms the original data matrix into a special ZData. This new one is a cell array of patches, of length n (60 in your code), each of them is an array of size [n*6,4]. So you cannot assign directly your new matrix to ZData.

There is one solution, besides recreating the plot each time. Basically, it modifies directly ZData. You can directly modify element by element Zdata. For that, try the following code instead of calling set(h,'Zdata', newH(i,j));:

for ih=j
    set(h(ih), 'ZData', kron(newH(i,ih),[nan 0 0 nan;0,1,1,0;0,1,1,0;nan 0 0 nan;nan 0 0 nan;nan nan nan nan]));
end

h is the handle of the plot; in the case of bar3, its length is n, the first dimension of your matrix. So, for each bar column, you set the ZData according to its format. Each element V of the matrix is transformed to this matrix:

NaN 0   0   NaN
0   V   V   0
0   V   V   0
NaN 0   0   NaN
NaN 0   0   NaN
NaN NaN NaN NaN

So, in order to build the complete ZData of each column, you call the function kron with the column of the updated matrix and with this atomic matrix.

This is not very fast; on my computer, the display lags time to time, but it is faster than recreating the bar plot each time. Using surf is more faster because there is less patches to draw.

OTHER TIPS

The problem lies in the way you handle the plotting.

h=bar3(newH);

plots the data and stores handles to patch graphic objects in h. When you write the following :

set(h,'Zdata', newH(i,j));

you assume that the handle 'Zdata' is a 60x60 array, which is not the case for bar3. Just write

output = get(h,'Zdata')

to see that. It requires a bit more data handling to do it this way but that seems tedious.

I propose an easy solution to this, simply replotting at every timestep :

oldH=H;
newH=H;
h=bar3(newH);
axis([1 n 1 n -2 8]);
k=0.2; %damping constant
c=2;   %wave speed

while 1==1
    newH(i,j)=H(i,j)+(1-k*dt)*(H(i,j)-oldH(i,j))-...
    dt^2*c^2/dx^2*((4*H(i,j)-H(i+1,j)-H(i-1,j)-H(i,j+1)-H(i,j-1))...
    +0.4*(4*H(i,j)-H(i+1,j+1)-H(i+1,j-1)-H(i-1,j+1)-H(i-1,j-1))); 
    h=bar3(newH);
    axis([1 n 1 n -2 8]);
    oldH=H;
    H=newH;
    pause(0.05);
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top