From octave-maintainers-request at bevo dot che dot wisc dot edu Fri Jan 30 11:47:51 2004 Subject: Re: contour plots and doing graphics in octave From: Donald J Bindner To: octave-maintainers at bevo dot che dot wisc dot edu Date: Fri, 30 Jan 2004 11:44:14 -0600 --AhhlLboLdkugWU4S Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Ok, I did some refining of my contour plots with the help of your previous comments. I am content with the results I get using Octave's "gplot" syntax. I get 2-D plots compatible with all of the other 2-D drawing in Octave, which means in particular that I can make a contour plot and then draw other figures on it. Don -- Don Bindner --AhhlLboLdkugWU4S Content-Type: text/x-c++src; charset=us-ascii Content-Disposition: attachment; filename="__cntr__.cc" #include #include #include #include #include #include #include static double mmin( const Matrix &m ) { double d; int i,j,nr,nc; nr = m.rows(); nc = m.columns(); if( nr==0 || nc==0 ) return 0.0; d = m(0,0); for(i = 0; i < nr; i++ ) { for( j = 0; j < nc; j++ ) { d = (m(i,j)d) ? m(i,j) : d; } } return d; } DEFUN_DLD( __cntr__, args, , "__cntr__ (x,y,z,levels): plot contour lines of a function\n\n" "Plot contour lines by interpolating the values of a function\n" "on a grid. If x,y,z are matrices with the same dimensions\n" "the the corresponding elements represent points on the function.\n" "levels contains a vector of heights at which to draw level curves.\n" ) { octave_value_list retval; int nargin = args.length(); int nr, nc, nl, i, j, k, count; double x11, x21, x12, x22, y11, y21, y12, y22, z11, z21, z12, z22; double c, x[8], y[8]; double minx, miny, maxx, maxy; std::string fname; FILE *f; char cmd[256]; int status; if( nargin != 4 ) { print_usage( "cnt" ); return retval; } Matrix xx = args(0).matrix_value(); Matrix yy = args(1).matrix_value(); Matrix zz = args(2).matrix_value(); ColumnVector level = ColumnVector( args(3).vector_value()); nl = level.length(); nr = xx.rows(); nc = xx.columns(); minx = mmin(xx); maxx = mmax(xx); miny = mmin(yy); maxy = mmax(yy); for( k = 0; k < nl; k++ ) { c = level(k); fname = tempnam ("", "oct-"); f = fopen( fname.c_str(), "w" ); mark_for_deletion( fname ); for( i = 0; i < nr-1; i++ ) { for( j = 0; j < nc-1; j++ ) { x11 = xx(i,j ); x21 = xx(i,j+1); x12 = xx(i+1,j); x22 = xx(i+1,j+1); y11 = yy(i,j ); y21 = yy(i,j+1); y12 = yy(i+1,j); y22 = yy(i+1,j+1); z11 = zz(i,j ); z21 = zz(i,j+1); z12 = zz(i+1,j); z22 = zz(i+1,j+1); count = 0; // find bottom intersection with contour if(( z11>c && z21c )) { x[count] = (c - z11)*(x21-x11)/(z21-z11) + x11; y[count] = (c - z11)*(y21-y11)/(z21-z11) + y11; count++; } // find top intersection with contour line if(( z12>c && z22c )) { x[count] = (c - z12)*(x22-x12)/(z22-z12) + x12; y[count] = (c - z12)*(y22-y12)/(z22-z12) + y12; count++; } // find left intersection with contour line if(( z11>c && z12c )) { x[count] = (c - z11)*(x12-x11)/(z12-z11) + x11; y[count] = (c - z11)*(y12-y11)/(z12-z11) + y11; count++; } // find right intersection with contour line if(( z21>c && z22c )) { x[count] = (c - z21)*(x22-x21)/(z22-z21) + x21; y[count] = (c - z21)*(y22-y21)/(z22-z21) + y21; count++; } // bottom left corner if( z11 == c ) { x[count] = x11; y[count] = y11; count++; } // bottom right corner if( z21 == c ) { x[count] = x21; y[count] = y21; count++; } // top left corner if( z12 == c ) { x[count] = x12; y[count] = y12; count++; } // top right corner if( z22 == c ) { x[count] = x22; y[count] = y22; count++; } // Only draw the contour if it crosses exactly two points on the boundary if( count == 2 ) { fprintf( f, "%lf %lf\n", x[0], y[0] ); fprintf( f, "%lf %lf\n", x[1], y[1] ); fprintf( f, "\n" ); } } } fclose( f ); snprintf( cmd, sizeof(cmd), "gplot \"%s\" title \"%g\"", fname.c_str(), c ); eval_string( std::string(cmd), false, status ); if( k == 0 ) eval_string( std::string("hold on"), false, status ); } return retval; } --AhhlLboLdkugWU4S Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="contour.m" function contour( x, y, z, levels ) # contour (x,y,z,levels): plot contour lines of a function # # Plot contour lines by interpolating the values of a function # on a grid. If x,y,z are matrices with the same dimensions # the the corresponding elements represent points on the function. # If levels is a scalar, it specifies a number of contour lines # to draw at evenly spaced heights. It can also be a vector of # specific heights at which to draw level curves. # # If x is a vector and y is a vector, then z must be a matrix # with the same number of rows as x and the same number of # columns as y. The corresponding points from which the contour # lines are interpolated are x(i),y(j),z(i,y). if( nargin < 3 ) usage( "contour(x,y,z,levels)" ); return; endif # If levels is unspecified, choose 5 level curves. if( nargin == 3 ) levels = 5; endif # If levels is a scalar, choose that many equally spaced curves. if( is_scalar( levels ) ) minz = min(min(z)); maxz = max(max(z)); diff = (maxz-minz)/(2*levels); levels = linspace(minz+diff,maxz-diff,levels ); endif if( !is_vector( levels )) error( "levels must be a vector or a scalar." ); return endif # If vector arguments were used, convert them to a # rectangular mesh first. if( is_vector(x) && is_vector(y)) if( length(x) != rows(z) ) error( "z must have the same number of rows as the length of x" ); return endif if( length(y) != columns(z) ) error( "z must have the same number of columns as the length of y" ); return endif [x,y] = meshgrid(x,y); endif if( rows(x) != rows(z) || rows(y) != rows(z) || columns(x) != columns(z) || columns(y) != columns(z) ) error( "Matrix arguments must all have the same dimensions" ); return; endif # Save the ishold state since we need to turn it on to # draw multiple contour lines. oldhold = ishold; __cntr__(x,y,z,levels); # reset the ishold state if it was off if( !oldhold ) hold off; endif endfunction --AhhlLboLdkugWU4S--