PLplot  5.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plcont.c
Go to the documentation of this file.
1 // Contour plotter.
2 //
3 // Copyright (C) 1995, 2000, 2001 Maurice LeBrun
4 // Copyright (C) 2000, 2002 Joao Cardoso
5 // Copyright (C) 2000-2014 Alan W. Irwin
6 // Copyright (C) 2004 Andrew Ross
7 //
8 // This file is part of PLplot.
9 //
10 // PLplot is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU Library General Public License as published
12 // by the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
14 //
15 // PLplot is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Library General Public License for more details.
19 //
20 // You should have received a copy of the GNU Library General Public License
21 // along with PLplot; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 
25 #include "plplotP.h"
26 
27 #ifdef MSDOS
28 #pragma optimize("",off)
29 #endif
30 
31 // Static function prototypes.
32 
33 static void
35  PLINT nx, PLINT ny, PLINT kx, PLINT lx,
36  PLINT ky, PLINT ly, PLFLT flev, PLINT **ipts,
37  PLTRANSFORM_callback pltr, PLPointer pltr_data );
38 
39 static void
41  PLINT nx, PLINT ny, PLINT kx, PLINT lx,
42  PLINT ky, PLINT ly, PLFLT flev, char *flabel, PLINT kcol, PLINT krow,
43  PLFLT lastx, PLFLT lasty, PLINT startedge,
44  PLINT **ipts, PLFLT *distance, PLINT *lastindex,
45  PLTRANSFORM_callback pltr, PLPointer pltr_data );
46 
47 static void
48 plfloatlabel( PLFLT value, char *string, PLINT len );
49 
50 static PLFLT
51 plP_pcwcx( PLINT x );
52 
53 static PLFLT
54 plP_pcwcy( PLINT y );
55 
56 static void
57 pl_drawcontlabel( PLFLT tpx, PLFLT tpy, char *flabel, PLFLT *distance, PLINT *lastindex );
58 
59 // Error flag for aborts
60 
61 static int error;
62 
63 //**************************************
64 //
65 // Defaults for contour label printing.
66 //
67 //**************************************
68 
69 // Font height for contour labels (normalized)
70 static PLFLT
72 
73 // Offset of label from contour line (if set to 0.0, labels are printed on the lines).
74 static PLFLT
76 
77 // Spacing parameter for contour labels
78 static PLFLT
80 
81 // Activate labels, default off
82 static PLINT
84 
85 // If the contour label exceed 10^(limexp) or 10^(-limexp), the exponential format is used
86 static PLINT
87  limexp = 4;
88 
89 // Number of significant digits
90 static PLINT
91  sigprec = 2;
92 
93 //******* contour lines storage ***************************
94 
95 static CONT_LEVEL *startlev = NULL;
98 
99 static int cont3d = 0;
100 
101 static CONT_LINE *
102 alloc_line( void )
103 {
104  CONT_LINE *line;
105 
106  if ( ( line = (CONT_LINE *) malloc( sizeof ( CONT_LINE ) ) ) == NULL )
107  {
108  plexit( "alloc_line: Insufficient memory" );
109  }
110 
111  line->x = (PLFLT *) malloc( LINE_ITEMS * sizeof ( PLFLT ) );
112  line->y = (PLFLT *) malloc( LINE_ITEMS * sizeof ( PLFLT ) );
113 
114  if ( ( line->x == NULL ) || ( line->y == NULL ) )
115  {
116  plexit( "alloc_line: Insufficient memory" );
117  }
118 
119  line->npts = 0;
120  line->next = NULL;
121 
122  return line;
123 }
124 
125 static CONT_LEVEL *
127 {
128  CONT_LEVEL *node;
129 
130  if ( ( node = (CONT_LEVEL *) malloc( sizeof ( CONT_LEVEL ) ) ) == NULL )
131  {
132  plexit( "alloc_level: Insufficient memory" );
133  }
134  node->level = level;
135  node->next = NULL;
136  node->line = alloc_line( );
137 
138  return node;
139 }
140 
141 static void
143 {
144  if ( ( ( line->x = (PLFLT *) realloc( line->x,
145  (size_t) ( line->npts + LINE_ITEMS ) * sizeof ( PLFLT ) ) ) == NULL ) ||
146  ( ( line->y = (PLFLT *) realloc( line->y,
147  (size_t) ( line->npts + LINE_ITEMS ) * sizeof ( PLFLT ) ) ) == NULL ) )
148  plexit( "realloc_line: Insufficient memory" );
149 }
150 
151 
152 // new contour level
153 static void
155 {
156  if ( cont3d )
157  {
158  if ( startlev == NULL )
159  {
160  startlev = alloc_level( level );
161  currlev = startlev;
162  }
163  else
164  {
165  currlev->next = alloc_level( level );
166  currlev = currlev->next;
167  }
168  currline = currlev->line;
169  }
170 }
171 
172 void
174 {
175  CONT_LINE *tline, *cline;
176  CONT_LEVEL *tlev, *clevel;
177 
178  if ( ct != NULL )
179  {
180  clevel = ct;
181 
182  do
183  {
184  cline = clevel->line;
185  do
186  {
187 #ifdef CONT_PLOT_DEBUG // for 2D plots. For 3D plots look at plot3.c:plotsh3di()
188  plP_movwor( cline->x[0], cline->y[0] );
189  for ( j = 1; j < cline->npts; j++ )
190  plP_drawor( cline->x[j], cline->y[j] );
191 #endif
192  tline = cline->next;
193  free( cline->x );
194  free( cline->y );
195  free( cline );
196  cline = tline;
197  }
198  while ( cline != NULL );
199  tlev = clevel->next;
200  free( clevel );
201  clevel = tlev;
202  }
203  while ( clevel != NULL );
204  startlev = NULL;
205  }
206 }
207 
208 static void
210 {
211  if ( cont3d )
212  {
213  PLINT pts = currline->npts;
214 
215  if ( pts % LINE_ITEMS == 0 )
216  realloc_line( currline );
217 
218  currline->x[pts] = xx;
219  currline->y[pts] = yy;
220  currline->npts++;
221  }
222  else
223  plP_drawor( xx, yy );
224 }
225 
226 static void
228 {
229  if ( cont3d )
230  {
231  if ( currline->npts != 0 ) // not an empty list, allocate new
232  {
233  currline->next = alloc_line( );
234  currline = currline->next;
235  }
236 
237  // and fill first element
238  currline->x[0] = xx;
239  currline->y[0] = yy;
240  currline->npts = 1;
241  }
242  else
243  plP_movwor( xx, yy );
244 }
245 
246 // small routine to set offset and spacing of contour labels, see desciption above
247 void c_pl_setcontlabelparam( PLFLT offset, PLFLT size, PLFLT spacing, PLINT active )
248 {
249  contlabel_offset = offset;
251  contlabel_space = spacing;
252  contlabel_active = active;
253 }
254 
255 // small routine to set the format of the contour labels, description of limexp and prec see above
256 void c_pl_setcontlabelformat( PLINT lexp, PLINT sigdig )
257 {
258  limexp = lexp;
259  sigprec = sigdig;
260 }
261 
262 static void pl_drawcontlabel( PLFLT tpx, PLFLT tpy, char *flabel, PLFLT *distance, PLINT *lastindex )
263 {
264  PLFLT delta_x, delta_y;
265  PLINT currx_old, curry_old;
266 
267  delta_x = plP_pcdcx( plsc->currx ) - plP_pcdcx( plP_wcpcx( tpx ) );
268  delta_y = plP_pcdcy( plsc->curry ) - plP_pcdcy( plP_wcpcy( tpy ) );
269 
270  currx_old = plsc->currx;
271  curry_old = plsc->curry;
272 
273  *distance += sqrt( delta_x * delta_x + delta_y * delta_y );
274 
275  plP_drawor( tpx, tpy );
276 
277  if ( (int) ( fabs( *distance / contlabel_space ) ) > *lastindex )
278  {
279  PLFLT scale, vec_x, vec_y, mx, my, dev_x, dev_y, off_x, off_y;
280 
281  vec_x = tpx - plP_pcwcx( currx_old );
282  vec_y = tpy - plP_pcwcy( curry_old );
283 
284  // Ensure labels appear the right way up
285  if ( vec_x < 0 )
286  {
287  vec_x = -vec_x;
288  vec_y = -vec_y;
289  }
290 
291  mx = (double) plsc->wpxscl / (double) plsc->phyxlen;
292  my = (double) plsc->wpyscl / (double) plsc->phyylen;
293 
294  dev_x = -my * vec_y / mx;
295  dev_y = mx * vec_x / my;
296 
297  scale = sqrt( ( mx * mx * dev_x * dev_x + my * my * dev_y * dev_y ) /
299 
300  off_x = dev_x / scale;
301  off_y = dev_y / scale;
302 
303  plptex( tpx + off_x, tpy + off_y, vec_x, vec_y, 0.5, flabel );
304  plP_movwor( tpx, tpy );
305  ( *lastindex )++;
306  }
307  else
308  plP_movwor( tpx, tpy );
309 }
310 
311 
312 // Format contour labels. Arguments:
313 // value: floating point number to be formatted
314 // string: the formatted label, plptex must be called with it to actually
315 // print the label
316 //
317 
318 static void plfloatlabel( PLFLT value, char *string, PLINT len )
319 {
320  PLINT setpre, precis;
321  // form[10] gives enough space for all non-malicious formats.
322  // tmpstring[15] gives enough room for 3 digits in a negative exponent
323  // or 4 digits in a positive exponent + null termination. That
324  // should be enough for all non-malicious use.
325  // Obviously there are security issues here that
326  // should be addressed as well.
327  //
328 #define FORM_LEN 10
329 #define TMPSTRING_LEN 15
330  char form[FORM_LEN], tmpstring[TMPSTRING_LEN];
331  PLINT exponent = 0;
332  PLFLT mant, tmp;
333 
334  PLINT prec = sigprec;
335 
336  plP_gprec( &setpre, &precis );
337 
338  if ( setpre )
339  prec = precis;
340 
341  if ( value > 0.0 )
342  tmp = log10( value );
343  else if ( value < 0.0 )
344  tmp = log10( -value );
345  else
346  tmp = 0;
347 
348  if ( tmp >= 0.0 )
349  exponent = (int) tmp;
350  else if ( tmp < 0.0 )
351  {
352  tmp = -tmp;
353  if ( floor( tmp ) < tmp )
354  exponent = -(int) ( floor( tmp ) + 1.0 );
355  else
356  exponent = -(int) ( floor( tmp ) );
357  }
358 
359  mant = value / pow( 10.0, exponent );
360 
361  if ( mant != 0.0 )
362  mant = (int) ( mant * pow( 10.0, prec - 1 ) + 0.5 * mant / fabs( mant ) ) / pow( 10.0, prec - 1 );
363 
364  snprintf( form, FORM_LEN, "%%.%df", prec - 1 );
365  snprintf( string, (size_t) len, form, mant );
366  snprintf( tmpstring, TMPSTRING_LEN, "#(229)10#u%d", exponent );
367  strncat( string, tmpstring, (size_t) len - strlen( string ) - 1 );
368 
369  if ( abs( exponent ) < limexp || value == 0.0 )
370  {
371  value = pow( 10.0, exponent ) * mant;
372 
373  if ( exponent >= 0 )
374  prec = prec - 1 - exponent;
375  else
376  prec = prec - 1 + abs( exponent );
377 
378  if ( prec < 0 )
379  prec = 0;
380 
381  snprintf( form, FORM_LEN, "%%.%df", (int) prec );
382  snprintf( string, (size_t) len, form, value );
383  }
384 }
385 
386 // physical coords (x) to world coords
387 
388 static PLFLT
390 {
391  return ( ( x - plsc->wpxoff ) / plsc->wpxscl );
392 }
393 
394 // physical coords (y) to world coords
395 
396 static PLFLT
398 {
399  return ( ( y - plsc->wpyoff ) / plsc->wpyscl );
400 }
401 
402 //--------------------------------------------------------------------------
403 // plf2eval1()
404 //
405 // Does a lookup from a 2d function array. Array is of type (PLFLT **),
406 // and is column dominant (normal C ordering).
407 //--------------------------------------------------------------------------
408 
409 PLFLT
410 plf2eval1( PLINT ix, PLINT iy, PLPointer plf2eval_data )
411 {
412  PLFLT value;
413  PLFLT **z = (PLFLT **) plf2eval_data;
414 
415  value = z[ix][iy];
416 
417  return value;
418 }
419 
420 //--------------------------------------------------------------------------
421 // plf2eval2()
422 //
423 // Does a lookup from a 2d function array. plf2eval_data is treated as type
424 // (PLfGrid2 *).
425 //--------------------------------------------------------------------------
426 
427 PLFLT
428 plf2eval2( PLINT ix, PLINT iy, PLPointer plf2eval_data )
429 {
430  PLFLT value;
431  PLfGrid2 *grid = (PLfGrid2 *) plf2eval_data;
432 
433  value = grid->f[ix][iy];
434 
435  return value;
436 }
437 
438 //--------------------------------------------------------------------------
439 // plf2eval()
440 //
441 // Does a lookup from a 2d function array. Array is of type (PLFLT *), and
442 // is column dominant (normal C ordering). You MUST fill the ny maximum
443 // array index entry in the PLfGrid struct.
444 //--------------------------------------------------------------------------
445 
446 PLFLT
447 plf2eval( PLINT ix, PLINT iy, PLPointer plf2eval_data )
448 {
449  PLFLT value;
450  PLfGrid *grid = (PLfGrid *) plf2eval_data;
451 
452  value = grid->f[ix * grid->ny + iy];
453 
454  return value;
455 }
456 
457 //--------------------------------------------------------------------------
458 // plf2evalr()
459 //
460 // Does a lookup from a 2d function array. Array is of type (PLFLT *), and
461 // is row dominant (Fortran ordering). You MUST fill the nx maximum array
462 // index entry in the PLfGrid struct.
463 //--------------------------------------------------------------------------
464 
465 PLFLT
466 plf2evalr( PLINT ix, PLINT iy, PLPointer plf2eval_data )
467 {
468  PLFLT value;
469  PLfGrid *grid = (PLfGrid *) plf2eval_data;
470 
471  value = grid->f[ix + iy * grid->nx];
472 
473  return value;
474 }
475 
476 //--------------------------------------------------------------------------
477 //
478 // cont_store:
479 //
480 // Draw contour lines in memory.
481 // cont_clean_store() must be called after use to release allocated memory.
482 //
483 //--------------------------------------------------------------------------
484 
485 void
487  PLINT ky, PLINT ly, PLFLT_VECTOR clevel, PLINT nlevel,
488  PLTRANSFORM_callback pltr, PLPointer pltr_data,
489  CONT_LEVEL **contour )
490 {
491  cont3d = 1;
492 
493  plcont( f, nx, ny, kx, lx, ky, ly, clevel, nlevel,
494  pltr, pltr_data );
495 
496  *contour = startlev;
497  cont3d = 0;
498 }
499 
500 //--------------------------------------------------------------------------
501 // void plcont()
502 //
503 // Draws a contour plot from data in f(nx,ny). Is just a front-end to
504 // plfcont, with a particular choice for f2eval and f2eval_data.
505 //--------------------------------------------------------------------------
506 
507 void
509  PLINT ky, PLINT ly, PLFLT_VECTOR clevel, PLINT nlevel,
510  PLTRANSFORM_callback pltr, PLPointer pltr_data )
511 {
513  nx, ny, kx, lx, ky, ly, clevel, nlevel,
514  pltr, pltr_data );
515 }
516 
517 //--------------------------------------------------------------------------
518 // void plfcont()
519 //
520 // Draws a contour plot using the function evaluator f2eval and data stored
521 // by way of the f2eval_data pointer. This allows arbitrary organizations
522 // of 2d array data to be used.
523 //
524 // The subrange of indices used for contouring is kx to lx in the x
525 // direction and from ky to ly in the y direction. The array of contour
526 // levels is clevel(nlevel), and "pltr" is the name of a function which
527 // transforms array indicies into world coordinates.
528 //
529 // Note that the fortran-like minimum and maximum indices (kx, lx, ky, ly)
530 // are translated into more C-like ones. I've only kept them as they are
531 // for the plcontf() argument list because of backward compatibility.
532 //--------------------------------------------------------------------------
533 
534 void
535 plfcont( PLF2EVAL_callback f2eval, PLPointer f2eval_data,
536  PLINT nx, PLINT ny, PLINT kx, PLINT lx,
537  PLINT ky, PLINT ly, PLFLT_VECTOR clevel, PLINT nlevel,
538  PLTRANSFORM_callback pltr, PLPointer pltr_data )
539 {
540  PLINT i, **ipts;
541 
542  if ( pltr == NULL )
543  {
544  // If pltr is undefined, abort with an error.
545  plabort( "plfcont: The pltr callback must be defined" );
546  return;
547  }
548 
549  if ( kx < 1 || kx >= lx )
550  {
551  plabort( "plfcont: indices must satisfy 1 <= kx <= lx <= nx" );
552  return;
553  }
554  if ( ky < 1 || ky >= ly )
555  {
556  plabort( "plfcont: indices must satisfy 1 <= ky <= ly <= ny" );
557  return;
558  }
559 
560  if ( ( ipts = (PLINT **) malloc( (size_t) nx * sizeof ( PLINT * ) ) ) == NULL )
561  {
562  plexit( "plfcont: Insufficient memory" );
563  }
564 
565  for ( i = 0; i < nx; i++ )
566  {
567  if ( ( ipts[i] = (PLINT *) malloc( (size_t) ny * sizeof ( PLINT * ) ) ) == NULL )
568  {
569  plexit( "plfcont: Insufficient memory" );
570  }
571  }
572 
573  for ( i = 0; i < nlevel; i++ )
574  {
575  plcntr( f2eval, f2eval_data,
576  nx, ny, kx - 1, lx - 1, ky - 1, ly - 1, clevel[i], ipts,
577  pltr, pltr_data );
578 
579  if ( error )
580  {
581  error = 0;
582  goto done;
583  }
584  }
585 
586 done:
587  for ( i = 0; i < nx; i++ )
588  {
589  free( (void *) ipts[i] );
590  }
591  free( (void *) ipts );
592 }
593 
594 //--------------------------------------------------------------------------
595 // void plcntr()
596 //
597 // The contour for a given level is drawn here. Note iscan has nx
598 // elements. ixstor and iystor each have nstor elements.
599 //--------------------------------------------------------------------------
600 
601 static void
602 plcntr( PLF2EVAL_callback f2eval, PLPointer f2eval_data,
603  PLINT nx, PLINT ny, PLINT kx, PLINT lx,
604  PLINT ky, PLINT ly, PLFLT flev, PLINT **ipts,
605  PLTRANSFORM_callback pltr, PLPointer pltr_data )
606 {
607  PLINT kcol, krow, lastindex;
608  PLFLT distance;
609  PLFLT save_def, save_scale;
610 
611  char flabel[30];
612  plgchr( &save_def, &save_scale );
613  save_scale = save_scale / save_def;
614 
615  cont_new_store( flev );
616 
617  // format contour label for plptex and define the font height of the labels
618  plfloatlabel( flev, flabel, 30 );
619  plschr( 0.0, contlabel_size );
620 
621  // Clear array for traversed squares
622  for ( kcol = kx; kcol < lx; kcol++ )
623  {
624  for ( krow = ky; krow < ly; krow++ )
625  {
626  ipts[kcol][krow] = 0;
627  }
628  }
629 
630 
631  for ( krow = ky; krow < ly; krow++ )
632  {
633  for ( kcol = kx; kcol < lx; kcol++ )
634  {
635  if ( ipts[kcol][krow] == 0 )
636  {
637  // Follow and draw a contour
638  pldrawcn( f2eval, f2eval_data,
639  nx, ny, kx, lx, ky, ly, flev, flabel, kcol, krow,
640  0.0, 0.0, -2, ipts, &distance, &lastindex,
641  pltr, pltr_data );
642 
643  if ( error )
644  return;
645  }
646  }
647  }
648  plschr( save_def, save_scale );
649 }
650 
651 //--------------------------------------------------------------------------
652 // void pldrawcn()
653 //
654 // Follow and draw a contour.
655 //--------------------------------------------------------------------------
656 
657 static void
658 pldrawcn( PLF2EVAL_callback f2eval, PLPointer f2eval_data,
659  PLINT nx, PLINT ny, PLINT kx, PLINT lx,
660  PLINT ky, PLINT ly, PLFLT flev, char *flabel, PLINT kcol, PLINT krow,
661  PLFLT lastx, PLFLT lasty, PLINT startedge, PLINT **ipts,
662  PLFLT *distance, PLINT *lastindex,
663  PLTRANSFORM_callback pltr, PLPointer pltr_data )
664 {
665  PLFLT f[4];
666  PLFLT px[4], py[4], locx[4], locy[4];
667  PLINT iedge[4];
668  PLINT i, j, k, num, first, inext, kcolnext, krownext, sfi, sfj;
669 
670 
671  ( *pltr )( kcol, krow + 1, &px[0], &py[0], pltr_data );
672  ( *pltr )( kcol, krow, &px[1], &py[1], pltr_data );
673  ( *pltr )( kcol + 1, krow, &px[2], &py[2], pltr_data );
674  ( *pltr )( kcol + 1, krow + 1, &px[3], &py[3], pltr_data );
675 
676  f[0] = f2eval( kcol, krow + 1, f2eval_data ) - flev;
677  f[1] = f2eval( kcol, krow, f2eval_data ) - flev;
678  f[2] = f2eval( kcol + 1, krow, f2eval_data ) - flev;
679  f[3] = f2eval( kcol + 1, krow + 1, f2eval_data ) - flev;
680 
681  for ( i = 0, j = 1; i < 4; i++, j = ( j + 1 ) % 4 )
682  {
683  // Use intermediates to avoid possible floating point
684  // under / over flow during multiplication.
685  sfi = ( f[i] > 0.0 ) ? 1 : ( ( f[i] < 0.0 ) ? -1 : 0 );
686  sfj = ( f[j] > 0.0 ) ? 1 : ( ( f[j] < 0.0 ) ? -1 : 0 );
687  iedge[i] = ( sfi * sfj > 0 ) ? -1 : ( ( sfi * sfj < 0 ) ? 1 : 0 );
688  }
689 
690  // Mark this square as done
691  ipts[kcol][krow] = 1;
692 
693  // Check if no contour has been crossed i.e. iedge[i] = -1
694  if ( ( iedge[0] == -1 ) && ( iedge[1] == -1 ) && ( iedge[2] == -1 )
695  && ( iedge[3] == -1 ) )
696  return;
697 
698  // Check if this is a completely flat square - in which case
699  // ignore it
700  if ( ( f[0] == 0.0 ) && ( f[1] == 0.0 ) && ( f[2] == 0.0 ) &&
701  ( f[3] == 0.0 ) )
702  return;
703 
704  // Calculate intersection points
705  num = 0;
706  if ( startedge < 0 )
707  {
708  first = 1;
709  }
710  else
711  {
712  locx[num] = lastx;
713  locy[num] = lasty;
714  num++;
715  first = 0;
716  }
717  for ( k = 0, i = ( startedge < 0 ? 0 : startedge ); k < 4; k++, i = ( i + 1 ) % 4 )
718  {
719  if ( i == startedge )
720  continue;
721 
722  // If the contour is an edge check it hasn't already been done
723  if ( f[i] == 0.0 && f[( i + 1 ) % 4] == 0.0 )
724  {
725  kcolnext = kcol;
726  krownext = krow;
727  if ( i == 0 )
728  kcolnext--;
729  if ( i == 1 )
730  krownext--;
731  if ( i == 2 )
732  kcolnext++;
733  if ( i == 3 )
734  krownext++;
735  if ( ( kcolnext < kx ) || ( kcolnext >= lx ) ||
736  ( krownext < ky ) || ( krownext >= ly ) ||
737  ( ipts[kcolnext][krownext] == 1 ) )
738  continue;
739  }
740  if ( ( iedge[i] == 1 ) || ( f[i] == 0.0 ) )
741  {
742  j = ( i + 1 ) % 4;
743  if ( f[i] != 0.0 )
744  {
745  locx[num] = ( px[i] * fabs( f[j] ) + px[j] * fabs( f[i] ) ) / fabs( f[j] - f[i] );
746  locy[num] = ( py[i] * fabs( f[j] ) + py[j] * fabs( f[i] ) ) / fabs( f[j] - f[i] );
747  }
748  else
749  {
750  locx[num] = px[i];
751  locy[num] = py[i];
752  }
753  // If this is the start of the contour then move to the point
754  if ( first == 1 )
755  {
756  cont_mv_store( locx[num], locy[num] );
757  first = 0;
758  *distance = 0;
759  *lastindex = 0;
760  }
761  else
762  {
763  // Link to the next point on the contour
764  if ( contlabel_active )
765  pl_drawcontlabel( locx[num], locy[num], flabel, distance, lastindex );
766  else
767  cont_xy_store( locx[num], locy[num] );
768  // Need to follow contour into next grid box
769  // Easy case where contour does not pass through corner
770  if ( f[i] != 0.0 )
771  {
772  kcolnext = kcol;
773  krownext = krow;
774  inext = ( i + 2 ) % 4;
775  if ( i == 0 )
776  kcolnext--;
777  if ( i == 1 )
778  krownext--;
779  if ( i == 2 )
780  kcolnext++;
781  if ( i == 3 )
782  krownext++;
783  if ( ( kcolnext >= kx ) && ( kcolnext < lx ) &&
784  ( krownext >= ky ) && ( krownext < ly ) &&
785  ( ipts[kcolnext][krownext] == 0 ) )
786  {
787  pldrawcn( f2eval, f2eval_data,
788  nx, ny, kx, lx, ky, ly, flev, flabel,
789  kcolnext, krownext,
790  locx[num], locy[num], inext, ipts,
791  distance, lastindex,
792  pltr, pltr_data );
793  }
794  }
795  // Hard case where contour passes through corner
796  // This is still not perfect - it may lose the contour
797  // which won't upset the contour itself (we can find it
798  // again later) but might upset the labelling
799  else
800  {
801  kcolnext = kcol;
802  krownext = krow;
803  inext = ( i + 2 ) % 4;
804  if ( i == 0 )
805  {
806  kcolnext--; krownext++;
807  }
808  if ( i == 1 )
809  {
810  krownext--; kcolnext--;
811  }
812  if ( i == 2 )
813  {
814  kcolnext++; krownext--;
815  }
816  if ( i == 3 )
817  {
818  krownext++; kcolnext++;
819  }
820  if ( ( kcolnext >= kx ) && ( kcolnext < lx ) &&
821  ( krownext >= ky ) && ( krownext < ly ) &&
822  ( ipts[kcolnext][krownext] == 0 ) )
823  {
824  pldrawcn( f2eval, f2eval_data,
825  nx, ny, kx, lx, ky, ly, flev, flabel,
826  kcolnext, krownext,
827  locx[num], locy[num], inext, ipts,
828  distance, lastindex,
829  pltr, pltr_data );
830  }
831  }
832  if ( first == 1 )
833  {
834  // Move back to first point
835  cont_mv_store( locx[num], locy[num] );
836  first = 0;
837  *distance = 0;
838  *lastindex = 0;
839  first = 0;
840  }
841  else
842  {
843  first = 1;
844  }
845  num++;
846  }
847  }
848  }
849 }
850 
851 //--------------------------------------------------------------------------
852 // pltr0()
853 //
854 // Identity transformation.
855 //--------------------------------------------------------------------------
856 
857 void
858 pltr0( PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer PL_UNUSED( pltr_data ) )
859 {
860  *tx = x;
861  *ty = y;
862 }
863 
864 //--------------------------------------------------------------------------
865 // pltr1()
866 //
867 // Does linear interpolation from singly dimensioned coord arrays.
868 //
869 // Just abort for now if coordinates are out of bounds (don't think it's
870 // possible, but if so we could use linear extrapolation).
871 //--------------------------------------------------------------------------
872 
873 void
874 pltr1( PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer pltr_data )
875 {
876  PLINT ul, ur, vl, vr;
877  PLFLT du, dv;
878  PLFLT xl, xr, yl, yr;
879 
880  PLcGrid *grid = (PLcGrid *) pltr_data;
881  PLFLT *xg = grid->xg;
882  PLFLT *yg = grid->yg;
883  PLINT nx = grid->nx;
884  PLINT ny = grid->ny;
885 
886  ul = (PLINT) x;
887  ur = ul + 1;
888  du = x - ul;
889 
890  vl = (PLINT) y;
891  vr = vl + 1;
892  dv = y - vl;
893 
894  if ( x < 0 || x > nx - 1 || y < 0 || y > ny - 1 )
895  {
896  plexit( "pltr1: Invalid coordinates" );
897  }
898 
899 // Look up coordinates in row-dominant array.
900 // Have to handle right boundary specially -- if at the edge, we'd better
901 // not reference the out of bounds point.
902 //
903 
904  xl = xg[ul];
905  yl = yg[vl];
906 
907  if ( ur == nx )
908  {
909  *tx = xl;
910  }
911  else
912  {
913  xr = xg[ur];
914  *tx = xl * ( 1 - du ) + xr * du;
915  }
916  if ( vr == ny )
917  {
918  *ty = yl;
919  }
920  else
921  {
922  yr = yg[vr];
923  *ty = yl * ( 1 - dv ) + yr * dv;
924  }
925 }
926 
927 //--------------------------------------------------------------------------
928 // pltr2()
929 //
930 // Does linear interpolation from doubly dimensioned coord arrays (column
931 // dominant, as per normal C 2d arrays).
932 //
933 // This routine includes lots of checks for out of bounds. This would occur
934 // occasionally due to some bugs in the contour plotter (now fixed). If an
935 // out of bounds coordinate is obtained, the boundary value is provided
936 // along with a warning. These checks should stay since no harm is done if
937 // if everything works correctly.
938 //--------------------------------------------------------------------------
939 
940 void
941 pltr2( PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer pltr_data )
942 {
943  PLINT ul, ur, vl, vr;
944  PLFLT du, dv;
945  PLFLT xll, xlr, xrl, xrr;
946  PLFLT yll, ylr, yrl, yrr;
947  PLFLT xmin, xmax, ymin, ymax;
948 
949  PLcGrid2 *grid = (PLcGrid2 *) pltr_data;
950  PLFLT **xg = grid->xg;
951  PLFLT **yg = grid->yg;
952  PLINT nx = grid->nx;
953  PLINT ny = grid->ny;
954 
955  ul = (PLINT) x;
956  ur = ul + 1;
957  du = x - ul;
958 
959  vl = (PLINT) y;
960  vr = vl + 1;
961  dv = y - vl;
962 
963  xmin = 0;
964  xmax = nx - 1;
965  ymin = 0;
966  ymax = ny - 1;
967 
968  if ( x < xmin || x > xmax || y < ymin || y > ymax )
969  {
970  plwarn( "pltr2: Invalid coordinates" );
971  if ( x < xmin )
972  {
973  if ( y < ymin )
974  {
975  *tx = xg[0][0];
976  *ty = yg[0][0];
977  }
978  else if ( y > ymax )
979  {
980  *tx = xg[0][ny - 1];
981  *ty = yg[0][ny - 1];
982  }
983  else
984  {
985  xll = xg[0][vl];
986  yll = yg[0][vl];
987  xlr = xg[0][vr];
988  ylr = yg[0][vr];
989 
990  *tx = xll * ( 1 - dv ) + xlr * ( dv );
991  *ty = yll * ( 1 - dv ) + ylr * ( dv );
992  }
993  }
994  else if ( x > xmax )
995  {
996  if ( y < ymin )
997  {
998  *tx = xg[nx - 1][0];
999  *ty = yg[nx - 1][0];
1000  }
1001  else if ( y > ymax )
1002  {
1003  *tx = xg[nx - 1][ny - 1];
1004  *ty = yg[nx - 1][ny - 1];
1005  }
1006  else
1007  {
1008  xll = xg[nx - 1][vl];
1009  yll = yg[nx - 1][vl];
1010  xlr = xg[nx - 1][vr];
1011  ylr = yg[nx - 1][vr];
1012 
1013  *tx = xll * ( 1 - dv ) + xlr * ( dv );
1014  *ty = yll * ( 1 - dv ) + ylr * ( dv );
1015  }
1016  }
1017  else
1018  {
1019  if ( y < ymin )
1020  {
1021  xll = xg[ul][0];
1022  xrl = xg[ur][0];
1023  yll = yg[ul][0];
1024  yrl = yg[ur][0];
1025 
1026  *tx = xll * ( 1 - du ) + xrl * ( du );
1027  *ty = yll * ( 1 - du ) + yrl * ( du );
1028  }
1029  else if ( y > ymax )
1030  {
1031  xlr = xg[ul][ny - 1];
1032  xrr = xg[ur][ny - 1];
1033  ylr = yg[ul][ny - 1];
1034  yrr = yg[ur][ny - 1];
1035 
1036  *tx = xlr * ( 1 - du ) + xrr * ( du );
1037  *ty = ylr * ( 1 - du ) + yrr * ( du );
1038  }
1039  }
1040  }
1041 
1042 // Normal case.
1043 // Look up coordinates in row-dominant array.
1044 // Have to handle right boundary specially -- if at the edge, we'd
1045 // better not reference the out of bounds point.
1046 //
1047 
1048  else
1049  {
1050  xll = xg[ul][vl];
1051  yll = yg[ul][vl];
1052 
1053  // ur is out of bounds
1054 
1055  if ( ur == nx && vr < ny )
1056  {
1057  xlr = xg[ul][vr];
1058  ylr = yg[ul][vr];
1059 
1060  *tx = xll * ( 1 - dv ) + xlr * ( dv );
1061  *ty = yll * ( 1 - dv ) + ylr * ( dv );
1062  }
1063 
1064  // vr is out of bounds
1065 
1066  else if ( ur < nx && vr == ny )
1067  {
1068  xrl = xg[ur][vl];
1069  yrl = yg[ur][vl];
1070 
1071  *tx = xll * ( 1 - du ) + xrl * ( du );
1072  *ty = yll * ( 1 - du ) + yrl * ( du );
1073  }
1074 
1075  // both ur and vr are out of bounds
1076 
1077  else if ( ur == nx && vr == ny )
1078  {
1079  *tx = xll;
1080  *ty = yll;
1081  }
1082 
1083  // everything in bounds
1084 
1085  else
1086  {
1087  xrl = xg[ur][vl];
1088  xlr = xg[ul][vr];
1089  xrr = xg[ur][vr];
1090 
1091  yrl = yg[ur][vl];
1092  ylr = yg[ul][vr];
1093  yrr = yg[ur][vr];
1094 
1095  *tx = xll * ( 1 - du ) * ( 1 - dv ) + xlr * ( 1 - du ) * ( dv ) +
1096  xrl * ( du ) * ( 1 - dv ) + xrr * ( du ) * ( dv );
1097 
1098  *ty = yll * ( 1 - du ) * ( 1 - dv ) + ylr * ( 1 - du ) * ( dv ) +
1099  yrl * ( du ) * ( 1 - dv ) + yrr * ( du ) * ( dv );
1100  }
1101  }
1102 }
1103 
1104 //--------------------------------------------------------------------------
1105 // pltr2p()
1106 //
1107 // Just like pltr2() but uses pointer arithmetic to get coordinates from 2d
1108 // grid tables. This form of grid tables is compatible with those from
1109 // PLplot 4.0. The grid data must be pointed to by a PLcGrid structure.
1110 //--------------------------------------------------------------------------
1111 
1112 void
1113 pltr2p( PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer pltr_data )
1114 {
1115  PLINT ul, ur, vl, vr;
1116  PLFLT du, dv;
1117  PLFLT xll, xlr, xrl, xrr;
1118  PLFLT yll, ylr, yrl, yrr;
1119  PLFLT xmin, xmax, ymin, ymax;
1120 
1121  PLcGrid *grid = (PLcGrid *) pltr_data;
1122  PLFLT *xg = grid->xg;
1123  PLFLT *yg = grid->yg;
1124  PLINT nx = grid->nx;
1125  PLINT ny = grid->ny;
1126 
1127  ul = (PLINT) x;
1128  ur = ul + 1;
1129  du = x - ul;
1130 
1131  vl = (PLINT) y;
1132  vr = vl + 1;
1133  dv = y - vl;
1134 
1135  xmin = 0;
1136  xmax = nx - 1;
1137  ymin = 0;
1138  ymax = ny - 1;
1139 
1140  if ( x < xmin || x > xmax || y < ymin || y > ymax )
1141  {
1142  plwarn( "pltr2p: Invalid coordinates" );
1143  if ( x < xmin )
1144  {
1145  if ( y < ymin )
1146  {
1147  *tx = *xg;
1148  *ty = *yg;
1149  }
1150  else if ( y > ymax )
1151  {
1152  *tx = *( xg + ( ny - 1 ) );
1153  *ty = *( yg + ( ny - 1 ) );
1154  }
1155  else
1156  {
1157  ul = 0;
1158  xll = *( xg + ul * ny + vl );
1159  yll = *( yg + ul * ny + vl );
1160  xlr = *( xg + ul * ny + vr );
1161  ylr = *( yg + ul * ny + vr );
1162 
1163  *tx = xll * ( 1 - dv ) + xlr * ( dv );
1164  *ty = yll * ( 1 - dv ) + ylr * ( dv );
1165  }
1166  }
1167  else if ( x > xmax )
1168  {
1169  if ( y < ymin )
1170  {
1171  *tx = *( xg + ( ny - 1 ) * nx );
1172  *ty = *( yg + ( ny - 1 ) * nx );
1173  }
1174  else if ( y > ymax )
1175  {
1176  *tx = *( xg + ( ny - 1 ) + ( nx - 1 ) * ny );
1177  *ty = *( yg + ( ny - 1 ) + ( nx - 1 ) * ny );
1178  }
1179  else
1180  {
1181  ul = nx - 1;
1182  xll = *( xg + ul * ny + vl );
1183  yll = *( yg + ul * ny + vl );
1184  xlr = *( xg + ul * ny + vr );
1185  ylr = *( yg + ul * ny + vr );
1186 
1187  *tx = xll * ( 1 - dv ) + xlr * ( dv );
1188  *ty = yll * ( 1 - dv ) + ylr * ( dv );
1189  }
1190  }
1191  else
1192  {
1193  if ( y < ymin )
1194  {
1195  vl = 0;
1196  xll = *( xg + ul * ny + vl );
1197  xrl = *( xg + ur * ny + vl );
1198  yll = *( yg + ul * ny + vl );
1199  yrl = *( yg + ur * ny + vl );
1200 
1201  *tx = xll * ( 1 - du ) + xrl * ( du );
1202  *ty = yll * ( 1 - du ) + yrl * ( du );
1203  }
1204  else if ( y > ymax )
1205  {
1206  vr = ny - 1;
1207  xlr = *( xg + ul * ny + vr );
1208  xrr = *( xg + ur * ny + vr );
1209  ylr = *( yg + ul * ny + vr );
1210  yrr = *( yg + ur * ny + vr );
1211 
1212  *tx = xlr * ( 1 - du ) + xrr * ( du );
1213  *ty = ylr * ( 1 - du ) + yrr * ( du );
1214  }
1215  }
1216  }
1217 
1218 // Normal case.
1219 // Look up coordinates in row-dominant array.
1220 // Have to handle right boundary specially -- if at the edge, we'd better
1221 // not reference the out of bounds point.
1222 //
1223 
1224  else
1225  {
1226  xll = *( xg + ul * ny + vl );
1227  yll = *( yg + ul * ny + vl );
1228 
1229  // ur is out of bounds
1230 
1231  if ( ur == nx && vr < ny )
1232  {
1233  xlr = *( xg + ul * ny + vr );
1234  ylr = *( yg + ul * ny + vr );
1235 
1236  *tx = xll * ( 1 - dv ) + xlr * ( dv );
1237  *ty = yll * ( 1 - dv ) + ylr * ( dv );
1238  }
1239 
1240  // vr is out of bounds
1241 
1242  else if ( ur < nx && vr == ny )
1243  {
1244  xrl = *( xg + ur * ny + vl );
1245  yrl = *( yg + ur * ny + vl );
1246 
1247  *tx = xll * ( 1 - du ) + xrl * ( du );
1248  *ty = yll * ( 1 - du ) + yrl * ( du );
1249  }
1250 
1251  // both ur and vr are out of bounds
1252 
1253  else if ( ur == nx && vr == ny )
1254  {
1255  *tx = xll;
1256  *ty = yll;
1257  }
1258 
1259  // everything in bounds
1260 
1261  else
1262  {
1263  xrl = *( xg + ur * ny + vl );
1264  xlr = *( xg + ul * ny + vr );
1265  xrr = *( xg + ur * ny + vr );
1266 
1267  yrl = *( yg + ur * ny + vl );
1268  ylr = *( yg + ul * ny + vr );
1269  yrr = *( yg + ur * ny + vr );
1270 
1271  *tx = xll * ( 1 - du ) * ( 1 - dv ) + xlr * ( 1 - du ) * ( dv ) +
1272  xrl * ( du ) * ( 1 - dv ) + xrr * ( du ) * ( dv );
1273 
1274  *ty = yll * ( 1 - du ) * ( 1 - dv ) + ylr * ( 1 - du ) * ( dv ) +
1275  yrl * ( du ) * ( 1 - dv ) + yrr * ( du ) * ( dv );
1276  }
1277  }
1278 }
1279 
1280 //--------------------------------------------------------------------------
1281 // pltr2f()
1282 //
1283 // Does linear interpolation from doubly dimensioned coord arrays
1284 // (row dominant, i.e. Fortran ordering).
1285 //
1286 // This routine includes lots of checks for out of bounds. This would
1287 // occur occasionally due to a bug in the contour plotter that is now fixed.
1288 // If an out of bounds coordinate is obtained, the boundary value is provided
1289 // along with a warning. These checks should stay since no harm is done if
1290 // if everything works correctly.
1291 //--------------------------------------------------------------------------
1292 
1293 void
1294 pltr2f( PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, void *pltr_data )
1295 {
1296  PLINT ul, ur, vl, vr;
1297  PLFLT du, dv;
1298  PLFLT xll, xlr, xrl, xrr;
1299  PLFLT yll, ylr, yrl, yrr;
1300  PLFLT xmin, xmax, ymin, ymax;
1301 
1302  PLcGrid *cgrid = (PLcGrid *) pltr_data;
1303  PLFLT *xg = cgrid->xg;
1304  PLFLT *yg = cgrid->yg;
1305  PLINT nx = cgrid->nx;
1306  PLINT ny = cgrid->ny;
1307 
1308  ul = (PLINT) x;
1309  ur = ul + 1;
1310  du = x - ul;
1311 
1312  vl = (PLINT) y;
1313  vr = vl + 1;
1314  dv = y - vl;
1315 
1316  xmin = 0;
1317  xmax = nx - 1;
1318  ymin = 0;
1319  ymax = ny - 1;
1320 
1321  if ( x < xmin || x > xmax || y < ymin || y > ymax )
1322  {
1323  plwarn( "pltr2f: Invalid coordinates" );
1324 
1325  if ( x < xmin )
1326  {
1327  if ( y < ymin )
1328  {
1329  *tx = *xg;
1330  *ty = *yg;
1331  }
1332  else if ( y > ymax )
1333  {
1334  *tx = *( xg + ( ny - 1 ) * nx );
1335  *ty = *( yg + ( ny - 1 ) * nx );
1336  }
1337  else
1338  {
1339  ul = 0;
1340  xll = *( xg + ul + vl * nx );
1341  yll = *( yg + ul + vl * nx );
1342  xlr = *( xg + ul + vr * nx );
1343  ylr = *( yg + ul + vr * nx );
1344 
1345  *tx = xll * ( 1 - dv ) + xlr * ( dv );
1346  *ty = yll * ( 1 - dv ) + ylr * ( dv );
1347  }
1348  }
1349  else if ( x > xmax )
1350  {
1351  if ( y < ymin )
1352  {
1353  *tx = *( xg + ( nx - 1 ) );
1354  *ty = *( yg + ( nx - 1 ) );
1355  }
1356  else if ( y > ymax )
1357  {
1358  *tx = *( xg + ( nx - 1 ) + ( ny - 1 ) * nx );
1359  *ty = *( yg + ( nx - 1 ) + ( ny - 1 ) * nx );
1360  }
1361  else
1362  {
1363  ul = nx - 1;
1364  xll = *( xg + ul + vl * nx );
1365  yll = *( yg + ul + vl * nx );
1366  xlr = *( xg + ul + vr * nx );
1367  ylr = *( yg + ul + vr * nx );
1368 
1369  *tx = xll * ( 1 - dv ) + xlr * ( dv );
1370  *ty = yll * ( 1 - dv ) + ylr * ( dv );
1371  }
1372  }
1373  else
1374  {
1375  if ( y < ymin )
1376  {
1377  vl = 0;
1378  xll = *( xg + ul + vl * nx );
1379  xrl = *( xg + ur + vl * nx );
1380  yll = *( yg + ul + vl * nx );
1381  yrl = *( yg + ur + vl * nx );
1382 
1383  *tx = xll * ( 1 - du ) + xrl * ( du );
1384  *ty = yll * ( 1 - du ) + yrl * ( du );
1385  }
1386  else if ( y > ymax )
1387  {
1388  vr = ny - 1;
1389  xlr = *( xg + ul + vr * nx );
1390  xrr = *( xg + ur + vr * nx );
1391  ylr = *( yg + ul + vr * nx );
1392  yrr = *( yg + ur + vr * nx );
1393 
1394  *tx = xlr * ( 1 - du ) + xrr * ( du );
1395  *ty = ylr * ( 1 - du ) + yrr * ( du );
1396  }
1397  }
1398  }
1399 
1400 // Normal case.
1401 // Look up coordinates in row-dominant array.
1402 // Have to handle right boundary specially -- if at the edge, we'd
1403 // better not reference the out of bounds point.
1404 
1405  else
1406  {
1407  xll = *( xg + ul + vl * nx );
1408  yll = *( yg + ul + vl * nx );
1409 
1410 // ur is out of bounds
1411 
1412  if ( ur == nx && vr < ny )
1413  {
1414  xlr = *( xg + ul + vr * nx );
1415  ylr = *( yg + ul + vr * nx );
1416 
1417  *tx = xll * ( 1 - dv ) + xlr * ( dv );
1418  *ty = yll * ( 1 - dv ) + ylr * ( dv );
1419  }
1420 
1421 // vr is out of bounds
1422 
1423  else if ( ur < nx && vr == ny )
1424  {
1425  xrl = *( xg + ur + vl * nx );
1426  yrl = *( yg + ur + vl * nx );
1427 
1428  *tx = xll * ( 1 - du ) + xrl * ( du );
1429  *ty = yll * ( 1 - du ) + yrl * ( du );
1430  }
1431 
1432 // both ur and vr are out of bounds
1433 
1434  else if ( ur == nx && vr == ny )
1435  {
1436  *tx = xll;
1437  *ty = yll;
1438  }
1439 
1440 // everything in bounds
1441 
1442  else
1443  {
1444  xrl = *( xg + ur + vl * nx );
1445  xlr = *( xg + ul + vr * nx );
1446  xrr = *( xg + ur + vr * nx );
1447 
1448  yrl = *( yg + ur + vl * nx );
1449  ylr = *( yg + ul + vr * nx );
1450  yrr = *( yg + ur + vr * nx );
1451  *tx = xll * ( 1 - du ) * ( 1 - dv ) + xlr * ( 1 - du ) * ( dv ) +
1452  xrl * ( du ) * ( 1 - dv ) + xrr * ( du ) * ( dv );
1453 
1454  *ty = yll * ( 1 - du ) * ( 1 - dv ) + ylr * ( 1 - du ) * ( dv ) +
1455  yrl * ( du ) * ( 1 - dv ) + yrr * ( du ) * ( dv );
1456  }
1457  }
1458 }
PLFLT plf2evalr(PLINT ix, PLINT iy, PLPointer plf2eval_data)
Definition: plcont.c:466
static CONT_LEVEL * startlev
Definition: plcont.c:95
void(* PLTRANSFORM_callback)(PLFLT x, PLFLT y, PLFLT_NC_SCALAR xp, PLFLT_NC_SCALAR yp, PL_GENERIC_POINTER data)
Definition: plplot.h:258
void pltr2f(PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, void *pltr_data)
Definition: plcont.c:1294
static PLFLT contlabel_offset
Definition: plcont.c:75
void plexit(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1948
PLFLT plP_pcdcy(PLINT y)
Definition: plcvt.c:95
PLINT plP_wcpcx(PLFLT x)
Definition: plcvt.c:63
#define plschr
Definition: plplot.h:792
static void cont_new_store(PLFLT level)
Definition: plcont.c:154
void plP_gprec(PLINT *p_setp, PLINT *p_prec)
Definition: plcore.c:3848
PLFLT plf2eval(PLINT ix, PLINT iy, PLPointer plf2eval_data)
Definition: plcont.c:447
PLINT nx
Definition: plplot.h:492
PL_NC_GENERIC_POINTER PLPointer
Definition: plplot.h:211
void plP_movwor(PLFLT x, PLFLT y)
Definition: plline.c:489
const PLFLT *const * PLFLT_MATRIX
Definition: plplot.h:254
PLFLT plf2eval2(PLINT ix, PLINT iy, PLPointer plf2eval_data)
Definition: plcont.c:428
void pltr1(PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer pltr_data)
Definition: plcont.c:874
struct cont_line * next
Definition: plplotP.h:777
struct cont_line * line
Definition: plplotP.h:784
void plabort(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1884
static int error
Definition: plcont.c:61
static void cont_mv_store(PLFLT xx, PLFLT yy)
Definition: plcont.c:227
static double distance(point *p1, point *p2)
Definition: csa.c:645
size_t size
Definition: plbuf.c:1701
#define TMPSTRING_LEN
static CONT_LINE * alloc_line(void)
Definition: plcont.c:102
PLFLT(* PLF2EVAL_callback)(PLINT ix, PLINT iy, PL_GENERIC_POINTER data)
Definition: plplot.h:260
int PLINT
Definition: plplot.h:174
PLFLT_NC_MATRIX f
Definition: plplot.h:502
static CONT_LINE * currline
Definition: plcont.c:97
PLINT npts
Definition: plplotP.h:776
static PLFLT contlabel_size
Definition: plcont.c:71
static void plcntr(PLF2EVAL_callback plf2eval, PLPointer plf2eval_data, PLINT nx, PLINT ny, PLINT kx, PLINT lx, PLINT ky, PLINT ly, PLFLT flev, PLINT **ipts, PLTRANSFORM_callback pltr, PLPointer pltr_data)
Definition: plcont.c:602
void c_plcont(PLFLT_MATRIX f, PLINT nx, PLINT ny, PLINT kx, PLINT lx, PLINT ky, PLINT ly, PLFLT_VECTOR clevel, PLINT nlevel, PLTRANSFORM_callback pltr, PLPointer pltr_data)
Definition: plcont.c:508
static void realloc_line(CONT_LINE *line)
Definition: plcont.c:142
Definition: plsdef.c:27
static PLFLT contlabel_space
Definition: plcont.c:79
static void pldrawcn(PLF2EVAL_callback plf2eval, PLPointer plf2eval_data, PLINT nx, PLINT ny, PLINT kx, PLINT lx, PLINT ky, PLINT ly, PLFLT flev, char *flabel, PLINT kcol, PLINT krow, PLFLT lastx, PLFLT lasty, PLINT startedge, PLINT **ipts, PLFLT *distance, PLINT *lastindex, PLTRANSFORM_callback pltr, PLPointer pltr_data)
Definition: plcont.c:658
#define snprintf
Definition: plplotP.h:235
PLFLT * x
Definition: plplotP.h:774
#define plgchr
Definition: plplot.h:718
static struct line line[]
PLFLT plf2eval1(PLINT ix, PLINT iy, PLPointer plf2eval_data)
Definition: plcont.c:410
#define plcont
Definition: plplot.h:702
static PLFLT plP_pcwcx(PLINT x)
Definition: plcont.c:389
static void pl_drawcontlabel(PLFLT tpx, PLFLT tpy, char *flabel, PLFLT *distance, PLINT *lastindex)
Definition: plcont.c:262
#define LINE_ITEMS
Definition: plplotP.h:770
PLFLT[][] yg
Definition: plplot.d:32
PLFLT * y
Definition: plplotP.h:775
PLFLT[] xg
Definition: plplot.d:25
static void cont_xy_store(PLFLT xx, PLFLT yy)
Definition: plcont.c:209
static PLINT limexp
Definition: plcont.c:87
PLFLT plP_pcdcx(PLINT x)
Definition: plcvt.c:87
PLINT ny
Definition: plplot.h:492
void pltr0(PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer PL_UNUSED(pltr_data))
Definition: plcont.c:858
static PLFLT value(double n1, double n2, double hue)
Definition: plctrl.c:1209
void pltr2(PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer pltr_data)
Definition: plcont.c:941
PLFLT[][] xg
Definition: plplot.d:31
#define FORM_LEN
static PLINT lastx
Definition: plline.c:29
static int cont3d
Definition: plcont.c:99
#define PL_UNUSED(x)
Definition: plplot.h:128
float PLFLT
Definition: plplot.h:157
void cont_clean_store(CONT_LEVEL *ct)
Definition: plcont.c:173
void c_pl_setcontlabelparam(PLFLT offset, PLFLT size, PLFLT spacing, PLINT active)
Definition: plcont.c:247
void plP_drawor(PLFLT x, PLFLT y)
Definition: plline.c:505
static PLINT lasty
Definition: plline.c:29
PLINT plP_wcpcy(PLFLT y)
Definition: plcvt.c:73
void c_pl_setcontlabelformat(PLINT lexp, PLINT sigdig)
Definition: plcont.c:256
void plwarn(PLCHAR_VECTOR errormsg)
Definition: plctrl.c:1853
static CONT_LEVEL * currlev
Definition: plcont.c:96
void cont_store(PLFLT_MATRIX f, PLINT nx, PLINT ny, PLINT kx, PLINT lx, PLINT ky, PLINT ly, PLFLT_VECTOR clevel, PLINT nlevel, PLTRANSFORM_callback pltr, PLPointer pltr_data, CONT_LEVEL **contour)
Definition: plcont.c:486
#define plptex
Definition: plplot.h:783
static PLFLT plP_pcwcy(PLINT y)
Definition: plcont.c:397
PLFLT[] yg
Definition: plplot.d:26
PLFLT level
Definition: plplotP.h:783
const PLFLT * PLFLT_VECTOR
Definition: plplot.h:245
static PLINT contlabel_active
Definition: plcont.c:83
static PLINT sigprec
Definition: plcont.c:91
void pltr2p(PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer pltr_data)
Definition: plcont.c:1113
void plfcont(PLF2EVAL_callback f2eval, PLPointer f2eval_data, PLINT nx, PLINT ny, PLINT kx, PLINT lx, PLINT ky, PLINT ly, PLFLT_VECTOR clevel, PLINT nlevel, PLTRANSFORM_callback pltr, PLPointer pltr_data)
Definition: plcont.c:535
static void plfloatlabel(PLFLT value, char *string, PLINT len)
Definition: plcont.c:318
PLFLT_FE_POINTER f
Definition: plplot.h:491
struct cont_level * next
Definition: plplotP.h:785
static CONT_LEVEL * alloc_level(PLFLT level)
Definition: plcont.c:126