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