1
/*===========================================================================
2
Copyright (C) 1995-2009 European Southern Observatory (ESO)
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License as
6
published by the Free Software Foundation; either version 2 of
7
the License, or (at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public
15
License along with this program; if not, write to the Free
16
Software Foundation, Inc., 675 Massachusetss Ave, Cambridge,
19
Corresponding concerning ESO-MIDAS should be addressed as follows:
20
Internet e-mail: midas@eso.org
21
Postal address: European Southern Observatory
22
Data Management Division
23
Karl-Schwarzschild-Strasse 2
24
D 85748 Garching bei Muenchen
26
===========================================================================*/
28
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
29
.IDENTifer module PLCON
30
.AUTHOR R.M. van Hees IPG-ESO Garching
31
.KEYWORDS plot software, graphics, bulk data fame, contour plotting
33
.PURPOSE Contour plotting routine for two dimensional data
34
.COMMENTS holds PLCON and PLCONI
35
.ENVIRONment MIDAS and AGL
36
#include <agl.h> Prototypes for AGL application programs
37
#include <midas_def.h> Prototypes for MIDAS interfaces
38
#include <plot_def.h> Symbols used by the PLT interfaces
40
.VERSION 1.3 14-Jul-1994 add option for colors RvH
41
1.2 25-Nov-1993 rewritten RvH
42
1.1 10-Sep-1993 FORTRAN --> C RvH
45
------------------------------------------------------------*/
47
* Define _POSIX_SOURCE to indicate
48
* that this is a POSIX program
50
#define _POSIX_SOURCE 1
53
* definition of the used functions in this module
60
#include <midas_def.h>
63
* define some macros and constants
71
* A segment from a isophote is defined by:
73
struct segmnt { int row; /* row in which the point is found */
74
int use; /* is it already used or not */
75
double x1; /* x coord of first point */
76
double y1; /* y coord of first point */
77
double x2; /* x coord of second point */
78
double y2; /* y coord of second point */
81
/*++++++++++++++++++++
82
.IDENTifer COLLECT_SEGMNT
83
.PURPOSE collect segments which together form the isophotes
84
input: double *start start value of the first pixel in w.c.
85
double *step distance between pixels in w.c.
86
int *npix size of the frame in pixels
87
float *p_img data of the frame
88
float levl value of the isophote
89
output: int nrdata number of structs point
90
struct segmnt *data pointer first struct point
91
.COMMENTS static function
92
--------------------*/
94
static void COLLECT_SEGMNT( double *start, double *step, int *npix,
95
float *p_img, float levl,
96
int *nrdata, struct segmnt *data )
98
static void COLLECT_SEGMNT( start, step, npix, p_img, levl,
102
double *start, *step;
109
double v1, v2, v3, v4, x, y;
111
struct segmnt *first;
116
for ( iy = 0; iy < npix[1]-1; iy++ )
118
for ( ix = 0; ix < npix[0]-1; ix++ )
120
v3 = *(p_img + npix[0]);
122
v4 = *(p_img + npix[0]);
125
if ( levl > v1 ) icase += 1;
126
if ( levl > v2 ) icase += 2;
127
if ( levl > v3 ) icase += 4;
128
if ( levl > v4 ) icase = 7 - icase;
132
{ if ( icase == 3 || icase == 4 )
134
data->y1 = y + step[1] * (levl-v1)/(v3-v1);;
137
{ data->x1 = x + step[0] * (levl-v1)/(v2-v1);
141
if ( icase == 1 || icase == 6 )
143
data->y2 = y + step[1] * (levl-v1)/(v3-v1);
144
if ( icase == 6 && (levl != v2 || levl != v3) )
145
{ data->row = iy + 1;
147
data->x1 = x + step[0] * (levl-v3)/(v4-v3);
148
data->y1 = y + step[1];
149
data->x2 = x + step[0];
150
data->y2 = y + step[1] * (levl-v2)/(v4-v2);
153
else if ( icase == 2 || icase == 3 )
154
{ data->x2 = x + step[0];
155
data->y2 = y + step[1] * (levl-v2)/(v4-v2);
158
{ data->x2 = x + step[0] * (levl-v3)/(v4-v3);
159
data->y2 = y + step[1];
165
{ data->x1 = x + step[0] * (levl-v3)/(v4-v3);
166
data->y1 = y + step[1];
167
data->x2 = x + step[0];
168
data->y2 = y + step[1] * (levl-v2)/(v4-v2);
178
*nrdata = data - first;
182
/*++++++++++++++++++++
183
.IDENTifer JOIN_SEGMNT
184
.PURPOSE Draw isophotes given a set of points
185
input: int nrdata number of structs point
186
struct segmnt *data pointer first struct point
187
.COMMENTS static function
188
--------------------*/
190
static void JOIN_SEGMNT( int nrdata, struct segmnt *data )
192
static void JOIN_SEGMNT( nrdata, data)
197
register int ii, indx;
199
int bgn, line, nr, stat, str_indx;
200
float *xdata, *ydata;
204
* if no points are found --> return
206
if ( nrdata < 1 ) return;
208
xx = (double *) osmmget( (nrdata+1) * sizeof( double ));
209
yy = (double *) osmmget( (nrdata+1) * sizeof( double ));
224
while ( indx < nrdata )
226
* search for next segment
229
while ( ++indx < nrdata && (data+indx)->row <= line + 1 )
230
{ if ( (data+indx)->use == FALSE &&
231
( (*xx == (data+indx)->x1 && *yy == (data+indx)->y1)
232
|| (*xx == (data+indx)->x2 && *yy == (data+indx)->y2)
237
if ( indx == nrdata || (data+indx)->row > line + 1 )
239
while ( --indx >= 0 && (data+indx)->row >= line - 1 )
240
{ if ( (data+indx)->use == FALSE &&
241
( (*xx == (data+indx)->x1 && *yy == (data+indx)->y1)
242
|| (*xx == (data+indx)->x2 && *yy == (data+indx)->y2)
247
if ( indx < 0 || (data+indx)->row < line - 1 ) stat = DRAW_C;
250
* do we have to draw a contour?
252
if ( stat == DRAW_C )
256
{ xdata = (float *) osmmget( ++nr * sizeof( float ));
257
ydata = (float *) osmmget( nr * sizeof( float ));
258
for ( ii = 0; ii < nr; ii++ )
259
{ xdata[ii] = (float) xx[ii];
260
ydata[ii] = (float) yy[ii];
262
AG_GPLL( xdata, ydata, nr );
263
(void) osmmfree( (char *) xdata );
264
(void) osmmfree( (char *) ydata );
267
* go to next starting point
270
while ( indx < nrdata && (data+indx)->use == TRUE ) indx++;
272
line = (data+indx)->row;
273
*xx = (data+indx)->x1;
274
*yy = (data+indx)->y1;
275
*++xx = (data+indx)->x2;
276
*++yy = (data+indx)->y2;
277
(data+indx)->use = TRUE;
283
if ( *xx == (data+indx)->x1 && *yy == (data+indx)->y1 )
284
{ *++xx = (data+indx)->x2;
285
*++yy = (data+indx)->y2;
288
{ *++xx = (data+indx)->x1;
289
*++yy = (data+indx)->y1;
291
line = (data+indx)->row;
292
(data+indx)->use = TRUE;
298
{ xdata = (float *) osmmget( ++nr * sizeof( float ));
299
ydata = (float *) osmmget( nr * sizeof( float ));
300
for ( ii = 0; ii < nr; ii++ )
301
{ xdata[ii] = (float) xx[ii];
302
ydata[ii] = (float) yy[ii];
304
AG_GPLL( xdata, ydata, nr );
305
(void) osmmfree( (char *) xdata );
306
(void) osmmfree( (char *) ydata );
308
(void) osmmfree( (char *) xx );
309
(void) osmmfree( (char *) yy );
313
/*++++++++++++++++++++++++++++++
315
.PURPOSE Contour plotting routine for two dimensional data
316
input: float *p_img pointer to the data of the frame
317
float *image image size in pixel coordinates
318
float *area image size in world coordinates
319
double *step distance between pixels in world units
320
int nlevl number of contours
321
float *clevl level of the contours
322
int *ctype ctype >= 0: array with line-types of contours
323
ctype < 0 : array with colors of contours
325
.COMMENTS if image[0] > image[1] or image[2] > image[3] then
326
the values are put in the right order
327
--------------------------------*/
328
void PLCON( p_img, image, area, step, nlevl, clevl, ctype )
330
float *p_img, *image, *area, *clevl;
337
int actvals, color, ctagl, ltype, ltagl, nrdata, npix[2];
343
* return if no contours have to be drawn
345
if ( nlevl == 0 ) return;
348
* find start values in x and y
351
start[0] = MYMAX( area[0], area[1] );
353
start[0] = MYMIN( area[0], area[1] );
356
start[1] = MYMAX( area[2], area[3] );
358
start[1] = MYMIN( area[2], area[3] );
361
* get line type from PLISTAT
363
PCKRDI( "LTYPE", 1, &actvals, <ype );
364
PCKRDI( "COLOR", 1, &actvals, &color );
365
ltagl = ltype = MYMAX( ltype-1, 0 );
367
(void) sprintf( text, "lstyl=%1d", ltype );
371
* get the points along the isophotes
373
npix[0] = (int) fabs( (double) image[1] - image[0] ) + 1;
374
npix[1] = (int) fabs( (double) image[3] - image[2] ) + 1;
375
data = (struct segmnt *) osmmget( npix[0]* npix[1]* sizeof( struct segmnt));
378
* collect the data isophote by isophote
380
for ( ic = 0; ic < nlevl; ic++ )
381
{ if ( ctype[ic] != ltagl && ctype[ic] != ctagl )
382
{ if ( ctype[ic] < 0 ) /* change color */
384
(void) sprintf( text, "color=%1d", -ctagl );
386
else /* change ltype */
388
(void) sprintf( text, "lstyl=%1d", ltagl );
393
* collect the segments
395
COLLECT_SEGMNT( start, step, npix, p_img, clevl[ic], &nrdata, data );
397
* join the segments and draw them in the current viewport
399
JOIN_SEGMNT( nrdata, data );
404
if ( ltype != ltagl )
405
{ (void) sprintf( text, "lstyl=%1d", ltype );
408
else if ( color != -ctagl )
409
{ (void) sprintf( text, "color=%1d", color );
412
(void) osmmfree( (char *) data );
415
/*++++++++++++++++++++++++++++++
417
.PURPOSE produce plot information for a two-dimensional contour plot
418
input: int plmode plot mode, see PMODE in PLISTAT
419
char *name data frame name
420
char *ident ascii identifier of image
421
float *clevl values of the contours
422
int *ctype ctype >= 0: array with line-types of contours
423
ctype < 0 : array with colors of contours
424
int nlevl number of contour levels
425
--------------------------------*/
426
void PLCONI( plmode, name, ident, clevl, ctype, nlevl )
427
int plmode, nlevl, *ctype;
431
int actvals, color, ii;
432
float one, ssize, tsize, x1, x2, y1, y2, xt, yt, yh, xstr;
433
float scale[2], mnmx[2], xl[3], yl[3], image[4], clpl[4], wndl[4];
437
* only plot mode is 2
439
if ( plmode != 2 ) return;
442
* get the symbol and character dimensions, from the MIDAS keywords
444
PCKRDR( "SSIZE", 1, &actvals, &ssize );
445
PCKRDR( "TSIZE", 1, &actvals, &tsize );
448
* if the symbol size or the text size is not equal to 1, set it to 1
449
* and call PCTSET to get the proper sizes for the MIDAS layout
451
if ( ssize != 1.0 || tsize != 1.0 )
453
PCKWRR( "SSIZE", 1, &one );
454
PCKWRR( "TSIZE", 1, &one );
461
(void) AG_RGET( "clpl", clpl );
462
(void) AG_RGET( "wndl", wndl );
467
AG_CDEF( x1, x2, y1, y2);
468
AG_WDEF( 0.0, 1.0, 0.0, 1.0 );
476
* set character height
478
AG_SSET( "sydi=0.75;chdi=0.75,0.75" );
479
AG_TGET( "M", xl, yl );
486
AG_GTXT( xt, yt, text, 1 );
492
if ( strlen( name ) > (size_t) 12 )
493
{ AG_GTXT( xt, yt, "Frame:", 1 );
495
AG_GTXT( xt, yt, name, 1 );
498
{ (void) sprintf( text, "Frame: %s", name );
499
AG_GTXT( xt, yt, text, 1 );
504
if ( strlen( ident ) > (size_t) 0 )
506
AG_GTXT( xt, yt, "Identification:", 1 );
508
AG_GTXT( xt, yt, ident, 1 );
513
PCKRDR( "PIXEL", 4, &actvals, image );
515
AG_GTXT( xt, yt, "Area:", 1 );
517
(void) sprintf( text, "X: %.0f to %.0f", image[0], image[1] );
518
AG_GTXT( xt, yt, text, 1 );
520
(void) sprintf( text, "Y: %.0f to %.0f", image[2], image[3] );
521
AG_GTXT( xt, yt, text, 1 );
525
PCKRDR( "SCALES", 2, &actvals, scale );
527
AG_GTXT( xt, yt, "Scales:", 1 );
529
(void) sprintf( text, "X: %-.6g", scale[0] );
530
AG_GTXT( xt, yt, text, 1 );
532
(void) sprintf( text, "Y: %-.6g", scale[1] );
533
AG_GTXT( xt, yt, text, 1 );
535
* minimum and maximum
537
PCKRDR( "ZWNDL", 2, &actvals, mnmx );
539
(void) sprintf( text, "Min: %-.3g ", mnmx[0] );
540
AG_GTXT( xt, yt, text, 1 );
542
(void) sprintf( text, "Max: %-.3g ", mnmx[1] );
543
AG_GTXT( xt, yt, text, 1 );
549
AG_GTXT( xt, yt, "Contour levels:", 1 );
551
for( ii = 0; ii < nlevl; ii++ )
552
{ xstr = xt + 11 * xl[1];
558
if ( ctype[ii] < 0 && color != ctype[ii] )
559
{ (void) sprintf( text, "color=%1d", -ctype[ii] );
564
(void) sprintf( text, "%8.5g", clevl[ii] );
565
AG_GTXT( xstr, yt, text, 1 );
567
if ( color != 1 ) AG_SSET( "color=1" );
573
* back to standard sizes
575
AG_CDEF( clpl[0], clpl[1], clpl[2], clpl[3] );
576
AG_WDEF( wndl[0], wndl[1], wndl[2], wndl[3] );
579
* reset if necessary the symbol and text size
581
if ( ssize != 1.0 || tsize != 1.0 )
582
{ PCKWRR( "SSIZE", 1, &ssize );
583
PCKWRR( "TSIZE", 1, &tsize );