1 //      3-d plot demo.
2 //
3 // Copyright (C) 2004  Alan W. Irwin
4 // Copyright (C) 2004  Rafael Laboissiere
5 //
6 // This file is part of PLplot.
7 //
8 // PLplot is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU Library General Public License as published
10 // by the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // PLplot is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU Library General Public License for more details.
17 //
18 // You should have received a copy of the GNU Library General Public License
19 // along with PLplot; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 //
22 //
23 //
24 
25 #include "plcdemos.h"
26 
27 // plexit not declared in public header!  However, explicit
28 // declaration (commented out below) does not work for g++ compiler
29 // (used for non-dynamic and static cases) for unknown reasons.  So
30 // use private header instead to declare plexit (which does work).
31 //PLDLLIMPEXP void
32 //plexit( PLCHAR_VECTOR errormsg );
33 #include "plplotP.h"
34 
35 // These values must be odd, for the middle
36 // of the index range to be an integer, and thus
37 // to correspond to the exact floating point centre
38 // of the sombrero.
39 #define XPTS    35              // Data points in x
40 #define YPTS    45              // Data points in y
41 
42 static PLFLT alt[] = { 60.0, 40.0 };
43 static PLFLT az[] = { 30.0, -30.0 };
44 static void cmap1_init( int );
45 
46 static PLCHAR_VECTOR title[] =
47 {
48     "#frPLplot Example 8 - Alt=60, Az=30",
49     "#frPLplot Example 8 - Alt=40, Az=-30",
50 };
51 
52 //--------------------------------------------------------------------------
53 // cmap1_init1
54 //
55 // Initializes color map 1 in HLS space.
56 // Basic grayscale variation from half-dark (which makes more interesting
57 // looking plot compared to dark) to light.
58 // An interesting variation on this:
59 //	s[1] = 1.0
60 //--------------------------------------------------------------------------
61 
62 static void
cmap1_init(int gray)63 cmap1_init( int gray )
64 {
65     PLFLT i[2], h[2], l[2], s[2];
66 
67     i[0] = 0.0;         // left boundary
68     i[1] = 1.0;         // right boundary
69 
70     if ( gray )
71     {
72         h[0] = 0.0;     // hue -- low: red (arbitrary if s=0)
73         h[1] = 0.0;     // hue -- high: red (arbitrary if s=0)
74 
75         l[0] = 0.5;     // lightness -- low: half-dark
76         l[1] = 1.0;     // lightness -- high: light
77 
78         s[0] = 0.0;     // minimum saturation
79         s[1] = 0.0;     // minimum saturation
80     }
81     else
82     {
83         h[0] = 240; // blue -> green -> yellow ->
84         h[1] = 0;   // -> red
85 
86         l[0] = 0.6;
87         l[1] = 0.6;
88 
89         s[0] = 0.8;
90         s[1] = 0.8;
91     }
92 
93     plscmap1n( 256 );
94     c_plscmap1l( 0, 2, i, h, l, s, NULL );
95 }
96 
97 //--------------------------------------------------------------------------
98 // main
99 //
100 // Does a series of 3-d plots for a given data set, with different
101 // viewing options in each plot.
102 //--------------------------------------------------------------------------
103 
104 
105 static int           rosen;
106 static int           if_plfsurf3d;
107 
108 static PLOptionTable options[] = {
109     {
110         "rosen",             // Turns on use of Rosenbrock function
111         NULL,
112         NULL,
113         &rosen,
114         PL_OPT_BOOL,
115         "-rosen",
116         "Use the log_e of the \"Rosenbrock\" function"
117     },
118     {
119         "if_plfsurf3d",
120         NULL,
121         NULL,
122         &if_plfsurf3d,
123         PL_OPT_BOOL,
124         "-if_plfsurf3d",
125         "Use C-only plfsurf3d API rather then usual cross-language plsurf3d API"
126     },
127     {
128         NULL,                   // option
129         NULL,                   // handler
130         NULL,                   // client data
131         NULL,                   // address of variable to set
132         0,                      // mode flag
133         NULL,                   // short syntax
134         NULL
135     }                           // long syntax
136 };
137 
138 #define LEVELS    10
139 
140 int
main(int argc,char * argv[])141 main( int argc, char *argv[] )
142 {
143     int      i, j, k;
144     PLFLT    *x, *y, **z;
145     // Shut up spurious undefined warnings from the compiler.
146     PLFLT    *z_row_major = NULL, *z_col_major = NULL;
147     PLFLT    dx           = 2. / (PLFLT) ( XPTS - 1 );
148     PLFLT    dy           = 2. / (PLFLT) ( YPTS - 1 );
149     PLfGrid2 grid_c, grid_row_major, grid_col_major;
150     PLFLT    xx, yy, r;
151     PLINT    ifshade;
152     PLFLT    zmin, zmax, step;
153     PLFLT    clevel[LEVELS];
154     PLINT    nlevel = LEVELS;
155 
156     PLINT    indexxmin = 0;
157     PLINT    indexxmax = XPTS;
158     PLINT    *indexymin;
159     PLINT    *indexymax;
160     PLFLT    **zlimited;
161     // parameters of ellipse (in x, y index coordinates) that limits the data.
162     // x0, y0 correspond to the exact floating point centre of the index
163     // range.
164     PLFLT x0 = 0.5 * (PLFLT) ( XPTS - 1 );
165     PLFLT a  = 0.9 * x0;
166     PLFLT y0 = 0.5 * (PLFLT) ( YPTS - 1 );
167     PLFLT b  = 0.7 * y0;
168     PLFLT square_root;
169 
170     // Parse and process command line arguments
171     plMergeOpts( options, "x08c options", NULL );
172     (void) plparseopts( &argc, argv, PL_PARSE_FULL );
173 
174     // Initialize plplot
175 
176     plinit();
177 
178 // Allocate data structures
179 
180     x = (PLFLT *) calloc( XPTS, sizeof ( PLFLT ) );
181     y = (PLFLT *) calloc( YPTS, sizeof ( PLFLT ) );
182 
183     plAlloc2dGrid( &z, XPTS, YPTS );
184     if ( if_plfsurf3d )
185     {
186         z_row_major = (PLFLT *) malloc( XPTS * YPTS * sizeof ( PLFLT ) );
187         z_col_major = (PLFLT *) malloc( XPTS * YPTS * sizeof ( PLFLT ) );
188         if ( !z_row_major || !z_col_major )
189             plexit( "Memory allocation error" );
190 
191         grid_c.f         = z;
192         grid_row_major.f = (PLFLT **) z_row_major;
193         grid_col_major.f = (PLFLT **) z_col_major;
194         grid_c.nx        = grid_row_major.nx = grid_col_major.nx = XPTS;
195         grid_c.ny        = grid_row_major.ny = grid_col_major.ny = YPTS;
196     }
197 
198     for ( i = 0; i < XPTS; i++ )
199     {
200         x[i] = -1. + (PLFLT) i * dx;
201         if ( rosen )
202             x[i] *= 1.5;
203     }
204 
205     for ( j = 0; j < YPTS; j++ )
206     {
207         y[j] = -1. + (PLFLT) j * dy;
208         if ( rosen )
209             y[j] += 0.5;
210     }
211 
212     for ( i = 0; i < XPTS; i++ )
213     {
214         xx = x[i];
215         for ( j = 0; j < YPTS; j++ )
216         {
217             yy = y[j];
218             if ( rosen )
219             {
220                 z[i][j] = pow( 1. - xx, 2. ) + 100. * pow( yy - pow( xx, 2. ), 2. );
221 
222                 // The log argument might be zero for just the right grid.
223                 if ( z[i][j] > 0. )
224                     z[i][j] = log( z[i][j] );
225                 else
226                     z[i][j] = -5.; // -MAXFLOAT would mess-up up the scale
227             }
228             else
229             {
230                 r       = sqrt( xx * xx + yy * yy );
231                 z[i][j] = exp( -r * r ) * cos( 2.0 * M_PI * r );
232             }
233 
234             if ( if_plfsurf3d )
235             {
236                 z_row_major[i * YPTS + j] = z[i][j];
237                 z_col_major[i + XPTS * j] = z[i][j];
238             }
239         }
240     }
241 
242     // Allocate and calculate y index ranges and corresponding zlimited.
243     plAlloc2dGrid( &zlimited, XPTS, YPTS );
244     indexymin = (PLINT *) malloc( XPTS * sizeof ( PLINT ) );
245     indexymax = (PLINT *) malloc( XPTS * sizeof ( PLINT ) );
246     if ( !indexymin || !indexymax )
247         plexit( "Memory allocation error" );
248 
249     //printf("XPTS = %d\n", XPTS);
250     //printf("x0 = %f\n", x0);
251     //printf("a = %f\n", a);
252     //printf("YPTS = %d\n", YPTS);
253     //printf("y0 = %f\n", y0);
254     //printf("b = %f\n", b);
255 
256     // These values should all be ignored because of the i index range.
257 #if 0
258     for ( i = 0; i < indexxmin; i++ )
259     {
260         indexymin[i] = 0;
261         indexymax[i] = YPTS;
262         for ( j = indexymin[i]; j < indexymax[i]; j++ )
263             // Mark with large value to check this is ignored.
264             zlimited[i][j] = 1.e300;
265     }
266 #endif
267     for ( i = indexxmin; i < indexxmax; i++ )
268     {
269         square_root = sqrt( 1. - MIN( 1., pow( ( i - x0 ) / a, 2. ) ) );
270         // Add 0.5 to find nearest integer and therefore preserve symmetry
271         // with regard to lower and upper bound of y range.
272         indexymin[i] = MAX( 0, (PLINT) ( 0.5 + y0 - b * square_root ) );
273         // indexymax calculated with the convention that it is 1
274         // greater than highest valid index.
275         indexymax[i] = MIN( YPTS, 1 + (PLINT) ( 0.5 + y0 + b * square_root ) );
276         //printf("i, b*square_root, indexymin[i], YPTS - indexymax[i] = %d, %e, %d, %d\n", i, b*square_root, indexymin[i], YPTS - indexymax[i]);
277 
278 #if 0
279         // These values should all be ignored because of the j index range.
280         for ( j = 0; j < indexymin[i]; j++ )
281             // Mark with large value to check this is ignored.
282             zlimited[i][j] = 1.e300;
283 #endif
284 
285         for ( j = indexymin[i]; j < indexymax[i]; j++ )
286             zlimited[i][j] = z[i][j];
287 
288 #if 0
289         // These values should all be ignored because of the j index range.
290         for ( j = indexymax[i]; j < YPTS; j++ )
291             // Mark with large value to check this is ignored.
292             zlimited[i][j] = 1.e300;
293 #endif
294     }
295 
296 #if 0
297     // These values should all be ignored because of the i index range.
298     for ( i = indexxmax; i < XPTS; i++ )
299     {
300         indexymin[i] = 0;
301         indexymax[i] = YPTS;
302         for ( j = indexymin[i]; j < indexymax[i]; j++ )
303             // Mark with large value to check this is ignored.
304             zlimited[i][j] = 1.e300;
305     }
306 #endif
307 
308     plMinMax2dGrid( (PLFLT_MATRIX) z, XPTS, YPTS, &zmax, &zmin );
309     step = ( zmax - zmin ) / ( nlevel + 1 );
310     for ( i = 0; i < nlevel; i++ )
311         clevel[i] = zmin + step + step * i;
312 
313     pllightsource( 1., 1., 1. );
314 
315     for ( k = 0; k < 2; k++ )
316     {
317         for ( ifshade = 0; ifshade < 5; ifshade++ )
318         {
319             pladv( 0 );
320             plvpor( 0.0, 1.0, 0.0, 0.9 );
321             plwind( -1.0, 1.0, -0.9, 1.1 );
322             plcol0( 3 );
323             plmtex( "t", 1.0, 0.5, 0.5, title[k] );
324             plcol0( 1 );
325             if ( rosen )
326                 plw3d( 1.0, 1.0, 1.0, -1.5, 1.5, -0.5, 1.5, zmin, zmax, alt[k], az[k] );
327             else
328                 plw3d( 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, zmin, zmax, alt[k], az[k] );
329 
330             plbox3( "bnstu", "x axis", 0.0, 0,
331                 "bnstu", "y axis", 0.0, 0,
332                 "bcdmnstuv", "z axis", 0.0, 0 );
333             plcol0( 2 );
334 
335             if ( ifshade == 0 ) // diffuse light surface plot
336             {
337                 cmap1_init( 1 );
338                 if ( if_plfsurf3d )
339                     plfsurf3d( x, y, plf2ops_c(), (PLPointer) z, XPTS, YPTS, 0, NULL, 0 );
340                 else
341                     plsurf3d( x, y, (PLFLT_MATRIX) z, XPTS, YPTS, 0, NULL, 0 );
342             }
343             else if ( ifshade == 1 ) // magnitude colored plot
344             {
345                 cmap1_init( 0 );
346                 if ( if_plfsurf3d )
347                     plfsurf3d( x, y, plf2ops_grid_c(), ( PLPointer ) & grid_c, XPTS, YPTS, MAG_COLOR, NULL, 0 );
348                 else
349                     plsurf3d( x, y, (PLFLT_MATRIX) z, XPTS, YPTS, MAG_COLOR, NULL, 0 );
350             }
351             else if ( ifshade == 2 ) //  magnitude colored plot with faceted squares
352             {
353                 cmap1_init( 0 );
354                 if ( if_plfsurf3d )
355                     plfsurf3d( x, y, plf2ops_grid_row_major(), ( PLPointer ) & grid_row_major, XPTS, YPTS, MAG_COLOR | FACETED, NULL, 0 );
356                 else
357                     plsurf3d( x, y, (PLFLT_MATRIX) z, XPTS, YPTS, MAG_COLOR | FACETED, NULL, 0 );
358             }
359             else if ( ifshade == 3 ) // magnitude colored plot with contours
360             {
361                 cmap1_init( 0 );
362                 if ( if_plfsurf3d )
363                     plfsurf3d( x, y, plf2ops_grid_col_major(), ( PLPointer ) & grid_col_major, XPTS, YPTS, MAG_COLOR | SURF_CONT | BASE_CONT, clevel, nlevel );
364                 else
365                     plsurf3d( x, y, (PLFLT_MATRIX) z, XPTS, YPTS, MAG_COLOR | SURF_CONT | BASE_CONT, clevel, nlevel );
366             }
367             else // magnitude colored plot with contours and index limits.
368             {
369                 cmap1_init( 0 );
370                 plsurf3dl( x, y, (PLFLT_MATRIX) zlimited, XPTS, YPTS, MAG_COLOR | SURF_CONT | BASE_CONT, clevel, nlevel, indexxmin, indexxmax, indexymin, indexymax );
371             }
372         }
373     }
374 
375 // Clean up
376 
377     free( (void *) x );
378     free( (void *) y );
379     plFree2dGrid( z, XPTS, YPTS );
380     if ( if_plfsurf3d )
381     {
382         free( (void *) z_row_major );
383         free( (void *) z_col_major );
384     }
385 
386     plFree2dGrid( zlimited, XPTS, YPTS );
387     free( (void *) indexymin );
388     free( (void *) indexymax );
389 
390     plend();
391 
392     exit( 0 );
393 }
394