1 #define MAIN_COXPLOT_FILE
2 #include "coxplot.h"
3
4 /*****************************************************************************
5 This software is copyrighted and owned by the Medical College of Wisconsin.
6 See the file README.Copyright for details.
7 ******************************************************************************/
8
9 static int num_plotar = 0 ;
10 static MEM_plotdata ** plotar = NULL ;
11 static int active_plot = -1 ;
12
13 static float active_color = (float) RGB_TO_COL(1.0,1.0,1.0) ;
14 static float active_thick = 0.0 ;
15
16 static float active_opacity = 1.0 ; /* 22 Jul 2004 */
17
18 #undef STATUS
19 #define STATUS(str) fprintf(stderr,"** " str "\n")
20
21 /*------------------------------------------------------------------------
22 Function to return a pointer to an in-memory plot with the given
23 ident. A NULL return value indicates failure.
24 A NULL input string will return the current "active" plot.
25 --------------------------------------------------------------------------*/
26
find_memplot(char * id)27 MEM_plotdata * find_memplot( char * id )
28 {
29 int ip ;
30
31 if( num_plotar == 0 || plotar == NULL ) return NULL ;
32
33 if( id == NULL || id[0] == '\0' ){
34 if( active_plot < 0 || active_plot >= num_plotar ) return NULL ;
35 return plotar[active_plot] ;
36 }
37
38 for( ip=0 ; ip < num_plotar ; ip++ )
39 if( strcmp(plotar[ip]->ident,id) == 0 ) return plotar[ip] ;
40
41 return NULL ;
42 }
43
44 /*------------------------------------------------------------------------
45 Function to create an in-memory plot with the given ident and aspect
46 ratio (length of x / length of y). Also sets the "active" plot to be
47 this new one. Nonzero return value indicates an error.
48 --------------------------------------------------------------------------*/
49
create_memplot(char * id,float aspect)50 int create_memplot( char * id , float aspect )
51 {
52 MEM_plotdata * pd ;
53 static int plotpak_framed = 0 ;
54 real asp ;
55
56 if( find_memplot(id) != NULL ) return 1 ;
57
58 INIT_MEMPLOT(pd,id) ;
59
60 if( plotar == NULL ){
61 plotar = (MEM_plotdata **) malloc( sizeof(MEM_plotdata *) ) ;
62 num_plotar = 0 ;
63 } else {
64 plotar = (MEM_plotdata **)
65 realloc( plotar , sizeof(MEM_plotdata *)*(num_plotar+1) ) ;
66 }
67
68 active_plot = num_plotar ;
69 plotar[num_plotar++] = pd ;
70
71 ADDTO_MEMPLOT( pd , 1.0,0.0,0.0,0.0 , 0.0 , -THCODE_OPAC ) ; /* 22 Jul 2004 */
72
73 if( aspect <= 0.0 ) aspect = 1.3 ;
74 asp = aspect ;
75 pd->aspect = aspect ;
76 memplt_( &asp ) ; /* setup PLOTPAK */
77
78 return 0 ;
79 }
80
81 /*------------------------------------------------------------------
82 20 Sep 2001: make a plot, fer shur
83 --------------------------------------------------------------------*/
84
create_memplot_surely(char * id,float aspect)85 int create_memplot_surely( char *id , float aspect )
86 {
87 int ii , jj ;
88 char str[256] ;
89
90 if( aspect <= 0.0 ) aspect = 1.0 ; /* backup for stupid users */
91
92 if( id != NULL && id[0] != '\0'){
93 ii = create_memplot(id,aspect) ;
94 if( ii == 0 ) return 0 ;
95 } else {
96 id = "ElvisWalksTheEarth" ;
97 }
98
99 for( jj=0 ; ; jj++ ){
100 sprintf(str,"%.240s_%d",id,jj) ;
101 ii = create_memplot(str,aspect) ;
102 if( ii == 0 ) return 0 ;
103 }
104
105 return 1 ; /* actually, unreachable */
106 }
107
108 /*-------------------------------------------------------------------------
109 Function to set the "active" plot to a given ident.
110 A nonzero return value indicates an error.
111 ---------------------------------------------------------------------------*/
112
set_active_memplot(char * id)113 int set_active_memplot( char * id )
114 {
115 int ip ;
116
117 if( id == NULL || id[0] == '\0' || num_plotar == 0 || plotar == NULL )
118 return 1 ;
119
120 for( ip=0 ; ip < num_plotar ; ip++ )
121 if( strcmp(plotar[ip]->ident,id) == 0 ){
122 real asp = plotar[ip]->aspect ;
123 active_plot = ip ;
124 memplt_( &asp ) ; /* re-setup PLOTPAK */
125 return 0 ;
126 }
127
128 return 1 ;
129 }
130
get_active_memplot(void)131 MEM_plotdata * get_active_memplot(void)
132 {
133 return find_memplot(NULL) ;
134 }
135
nline_active_memplot(void)136 int nline_active_memplot(void)
137 {
138 MEM_plotdata * mp ;
139 mp = find_memplot(NULL) ;
140 if( mp == NULL ) return 0 ;
141 return MEMPLOT_NLINE(mp) ;
142 }
143
144 /*-------------------------------------------------------------------------
145 Functions to set line thickness and color.
146 Color is given as an RGB triple from [0,1] x [0,1] x [0,1].
147 Thickness is given in the same units as coordinates; zero means thin.
148 ---------------------------------------------------------------------------*/
149
set_color_memplot(float r,float g,float b)150 void set_color_memplot( float r , float g , float b )
151 {
152 if( r > 1.0 || g > 1.0 || b > 1.0 ){ /* 22 Mar 2002: */
153 r /= 255.0 ; g /= 255.0 ; b /= 255.0 ; /* allow for 0..255 */
154 }
155 if( r < 0.0 ) r = 0.0 ; else if ( r > 1.0 ) r = 1.0 ;
156 if( g < 0.0 ) g = 0.0 ; else if ( g > 1.0 ) g = 1.0 ;
157 if( b < 0.0 ) b = 0.0 ; else if ( b > 1.0 ) b = 1.0 ;
158
159 active_color = (float) RGB_TO_COL(r,g,b) ;
160 return ;
161 }
162
163 /*----- This routine is called from color.f -----*/
164
zzmpco_(float * r,float * g,float * b)165 void zzmpco_( float * r , float * g , float * b )
166 {
167 set_color_memplot( *r , *g , *b ) ;
168 return ;
169 }
170
set_thick_memplot(float th)171 void set_thick_memplot( float th )
172 {
173 if( th < 0.0 ) th = 0.0 ;
174 active_thick = th ;
175 return ;
176 }
177
get_thick_memplot(void)178 float get_thick_memplot( void )
179 {
180 return active_thick ;
181 }
182
set_opacity_memplot(float th)183 void set_opacity_memplot( float th ) /* 22 Jul 2004 */
184 {
185 MEM_plotdata *mp ;
186
187 if( th < 0.0 ) th = 0.0 ;
188 else if( th > 1.0 ) th = 1.0 ;
189 active_opacity = th ;
190
191 /* Set opacity for further drawing [22 Jul 2004] */
192
193 if( active_plot < 0 || active_plot >= num_plotar ||
194 num_plotar == 0 || plotar == NULL ||
195 plotar[active_plot] == NULL ) return ;
196
197 mp = plotar[active_plot] ;
198 ADDTO_MEMPLOT( mp , th,0.0,0.0,0.0 , 0.0 , -THCODE_OPAC ) ;
199 return ;
200 }
201
get_opacity_memplot(void)202 float get_opacity_memplot( void )
203 {
204 return active_opacity ;
205 }
206
207 /*------------------------------------------------------------------
208 where the actual plotting into the memplot is done from
209 the coxplot functions
210 --------------------------------------------------------------------*/
211
plotline_memplot(float x1,float y1,float x2,float y2)212 void plotline_memplot( float x1 , float y1 , float x2 , float y2 )
213 {
214 MEM_plotdata * mp ;
215
216 if( active_plot < 0 || active_plot >= num_plotar ||
217 num_plotar == 0 || plotar == NULL ||
218 plotar[active_plot] == NULL ) return ;
219
220 mp = plotar[active_plot] ;
221
222 #if 0
223 fprintf(stderr,"** plotline_memplot %d: (%f,%f) to (%f,%f)\n",
224 MEMPLOT_NLINE(mp) , x1,y1,x2,y2) ;
225 #endif
226
227 ADDTO_MEMPLOT( mp , x1,y1,x2,y2 , active_color , active_thick ) ;
228 return ;
229 }
230
plotrect_memplot(float x1,float y1,float x2,float y2)231 void plotrect_memplot( float x1 , float y1 , float x2 , float y2 ) /* 21 Mar 2001 */
232 {
233 MEM_plotdata * mp ;
234
235 if( active_plot < 0 || active_plot >= num_plotar ||
236 num_plotar == 0 || plotar == NULL ||
237 plotar[active_plot] == NULL ) return ;
238
239 mp = plotar[active_plot] ;
240
241 ADDTO_MEMPLOT( mp , x1,y1,x2,y2 , active_color , -THCODE_RECT ) ;
242 return ;
243 }
244
plotfrect_memplot(float x1,float y1,float x2,float y2)245 void plotfrect_memplot( float x1 , float y1 , float x2 , float y2 ) /* 24 Apr 2012 */
246 {
247 MEM_plotdata * mp ;
248
249 if( active_plot < 0 || active_plot >= num_plotar ||
250 num_plotar == 0 || plotar == NULL ||
251 plotar[active_plot] == NULL ) return ;
252
253 mp = plotar[active_plot] ;
254
255 ADDTO_MEMPLOT( mp , x1,y1,x2,y2 , active_color , -THCODE_FRECT ) ;
256 return ;
257 }
258
plotcirc_memplot(float x1,float y1,float rad)259 void plotcirc_memplot( float x1 , float y1 , float rad ) /* 10 Mar 2002 */
260 {
261 MEM_plotdata * mp ;
262
263 if( active_plot < 0 || active_plot >= num_plotar ||
264 num_plotar == 0 || plotar == NULL ||
265 plotar[active_plot] == NULL ) return ;
266
267 mp = plotar[active_plot] ;
268
269 ADDTO_MEMPLOT( mp , x1,y1,rad,0.0 , active_color , -THCODE_CIRC ) ;
270 return ;
271 }
272
plotball_memplot(float x1,float y1,float rad)273 void plotball_memplot( float x1 , float y1 , float rad )
274 {
275 MEM_plotdata * mp ;
276
277 if( active_plot < 0 || active_plot >= num_plotar ||
278 num_plotar == 0 || plotar == NULL ||
279 plotar[active_plot] == NULL ) return ;
280
281 mp = plotar[active_plot] ;
282
283 ADDTO_MEMPLOT( mp , x1,y1,rad,0.0 , active_color , -THCODE_BALL ) ;
284 return ;
285 }
286
287 /*----- This routine is called from zzphph.f to draw 1 actual line -----*/
288
zzmpli_(float * x1,float * y1,float * x2,float * y2)289 void zzmpli_( float * x1 , float * y1 , float * x2 , float * y2 )
290 {
291 plotline_memplot( *x1 , *y1 , *x2 , *y2 ) ;
292 return ;
293 }
294
295 /*------------------------------------------------------------------------
296 Delete the active in-memory plot.
297 After this, there is no "active" plot.
298 --------------------------------------------------------------------------*/
299
delete_active_memplot(void)300 void delete_active_memplot(void)
301 {
302 int ip ;
303
304 if( active_plot < 0 || active_plot >= num_plotar ||
305 num_plotar == 0 || plotar == NULL ||
306 plotar[active_plot] == NULL ) return ;
307
308 DESTROY_MEMPLOT( plotar[active_plot] ) ;
309
310 if( num_plotar == 1 ){
311 free(plotar) ; plotar = NULL ; num_plotar = 0 ;
312 } else {
313 for( ip=active_plot+1 ; ip < num_plotar ; ip++ ) plotar[ip-1] = plotar[ip] ;
314 num_plotar-- ; plotar[num_plotar] = NULL ;
315 }
316
317 active_plot = -1 ;
318 return ;
319 }
320
321 /*------------------------------------------------------------------------*/
322
delete_memplot(MEM_plotdata * mp)323 void delete_memplot( MEM_plotdata * mp )
324 {
325 int ip ;
326
327 if( num_plotar == 0 || plotar == NULL || mp == NULL ) return ;
328
329 for( ip=0 ; ip < num_plotar ; ip++ ) if( plotar[ip] == mp ) break ;
330
331 if( ip < num_plotar ){
332 if( active_plot == ip ) active_plot = -1 ;
333 else if( active_plot > ip ) active_plot-- ;
334
335 for( ip++ ; ip < num_plotar ; ip++ ) plotar[ip-1] = plotar[ip] ;
336
337 num_plotar-- ; plotar[num_plotar] = NULL ;
338 }
339
340 DESTROY_MEMPLOT( mp ) ;
341 return ;
342 }
343
344 /*-----------------------------------------------------------------------
345 Scale data inside an memplot -- 26 Feb 2001
346 x_new = sx * x_old + tx
347 y_new = sy * y_old + ty
348 thick_new = st * thick_old
349 -------------------------------------------------------------------------*/
350
scale_memplot(float sx,float tx,float sy,float ty,float st,MEM_plotdata * mp)351 void scale_memplot( float sx , float tx ,
352 float sy , float ty , float st , MEM_plotdata * mp )
353 {
354 int ii,nn ;
355 if( mp == NULL ) return ;
356
357 for( nn=ii=0 ; ii < mp->nxyline ; ii++ ){
358 if( mp->xyline[nn+5] == -THCODE_OPAC ){ /* 21 Mar 2017 */
359 nn += 6 ;
360 } else {
361 mp->xyline[nn] = mp->xyline[nn] * sx + tx ; nn++ ; /* x1 */
362 mp->xyline[nn] = mp->xyline[nn] * sy + ty ; nn++ ; /* y1 */
363 mp->xyline[nn] = mp->xyline[nn] * sx + tx ; nn++ ; /* x2 */
364 mp->xyline[nn] = mp->xyline[nn] * sy + ty ; nn++ ; /* y2 */
365 /** no change here */ nn++ ; /* color */
366 if( mp->xyline[nn] > 0.0f )
367 mp->xyline[nn] = mp->xyline[nn] * st ; nn++ ; /* thick */
368 }
369 }
370 return ;
371 }
372
373 /*-----------------------------------------------------------------------
374 Append data from one memplot to another -- 26 Feb 2001
375 -------------------------------------------------------------------------*/
376
append_to_memplot(MEM_plotdata * mp,MEM_plotdata * ap)377 void append_to_memplot( MEM_plotdata * mp , MEM_plotdata * ap )
378 {
379 int nn , nold ;
380 if( mp == NULL || ap == NULL || ap->nxyline <= 0 ) return ;
381
382 nn = mp->nxyline + ap->nxyline ;
383 mp->xyline = (float *) realloc(mp->xyline,
384 sizeof(float)*NXY_MEMPLOT*nn) ;
385
386 memcpy( mp->xyline + NXY_MEMPLOT*mp->nxyline ,
387 ap->xyline , sizeof(float)*NXY_MEMPLOT*ap->nxyline ) ;
388
389 mp->nxyline = mp->nxyline_all = nn ;
390 return ;
391 }
392
393 /*-----------------------------------------------------------------------
394 Make a copy of a memplot; the new one will be the active memplot
395 -- 26 Feb 2001 -- RWCox
396 -------------------------------------------------------------------------*/
397
copy_memplot(MEM_plotdata * mp)398 MEM_plotdata * copy_memplot( MEM_plotdata * mp )
399 {
400 MEM_plotdata * np ;
401 char str[256] ; int nn ;
402
403 if( mp == NULL ) return NULL ;
404
405 /* make a new ID string */
406
407 for( nn=1 ; nn <= 9999 ; nn++ ){
408 sprintf(str,"%.240sCopy%04d",mp->ident,nn) ;
409 if( find_memplot(str) == NULL ) break ;
410 }
411 if( nn == 1000 ) return NULL ; /* this is bad (but unlikely) */
412
413 /* make the new memplot */
414
415 nn = create_memplot( str , mp->aspect ) ;
416 if( nn ) return NULL ; /* this is real bad */
417
418 np = find_memplot(NULL) ; /* is the new one */
419 if( np == NULL ) return NULL ; /* shouldn't happen */
420
421 /* copy data from old one into new one */
422
423 nn = np->nxyline = np->nxyline_all = mp->nxyline ;
424 np->xyline = (float *) realloc(np->xyline,
425 sizeof(float)*NXY_MEMPLOT*nn) ;
426 memcpy( np->xyline , mp->xyline , sizeof(float)*NXY_MEMPLOT*nn ) ;
427
428 return np ;
429 }
430
431 /*----------------------------------------------------------------------
432 Flip a memplot inplace - 30 Aug 2001 - RWCox
433 rot = one of the MRI_ROT_ codes (see coxplot.h)
434 mirror = whether to left-right mirror after rotation
435 ------------------------------------------------------------------------*/
436
flip_memplot(int rot,int mirror,MEM_plotdata * mp)437 void flip_memplot( int rot , int mirror , MEM_plotdata *mp )
438 {
439 int fopt , ii,nn ;
440 float xtop , ytop=1.0 , x1,y1,x2,y2 ;
441 int thc ;
442
443 if( mp == NULL ) return ; /* nothing in */
444 if( rot == MRI_ROT_0 && mirror == FALSE ) return ; /* do nothing */
445
446 xtop = mp->aspect ;
447
448 fopt = (mirror) ? (rot+MRI_FLMADD) : (rot) ;
449 switch( fopt ){
450
451 default: return ; /* should never happen */
452
453 case MRI_ROT_90:
454 for( nn=ii=0 ; ii < mp->nxyline ; ii++,nn+=NXY_MEMPLOT ){
455 x1 = mp->xyline[nn ] ; y1 = mp->xyline[nn+1] ;
456 x2 = mp->xyline[nn+2] ; y2 = mp->xyline[nn+3] ;
457 thc = (int)mp->xyline[nn+5] ; if( thc == -THCODE_OPAC ) continue ;
458 mp->xyline[nn ] = ytop - y1 ;
459 mp->xyline[nn+1] = x1 ; if( thc == -THCODE_CIRC || thc == -THCODE_BALL ) continue ;
460 mp->xyline[nn+2] = ytop - y2 ;
461 mp->xyline[nn+3] = x2 ;
462 }
463 break ;
464
465 case MRI_ROT_180:
466 for( nn=ii=0 ; ii < mp->nxyline ; ii++,nn+=NXY_MEMPLOT ){
467 x1 = mp->xyline[nn ] ; y1 = mp->xyline[nn+1] ;
468 x2 = mp->xyline[nn+2] ; y2 = mp->xyline[nn+3] ;
469 thc = (int)mp->xyline[nn+5] ; if( thc == -THCODE_OPAC ) continue ;
470 mp->xyline[nn ] = xtop - x1 ;
471 mp->xyline[nn+1] = ytop - y1 ; if( thc == -THCODE_CIRC || thc == -THCODE_BALL ) continue ;
472 mp->xyline[nn+2] = xtop - x2 ;
473 mp->xyline[nn+3] = ytop - y2 ;
474 }
475 break ;
476
477 case MRI_ROT_270:
478 for( nn=ii=0 ; ii < mp->nxyline ; ii++,nn+=NXY_MEMPLOT ){
479 x1 = mp->xyline[nn ] ; y1 = mp->xyline[nn+1] ;
480 x2 = mp->xyline[nn+2] ; y2 = mp->xyline[nn+3] ;
481 thc = (int)mp->xyline[nn+5] ; if( thc == -THCODE_OPAC ) continue ;
482 mp->xyline[nn ] = y1 ;
483 mp->xyline[nn+1] = xtop - x1 ; if( thc == -THCODE_CIRC || thc == -THCODE_BALL ) continue ;
484 mp->xyline[nn+2] = y2 ;
485 mp->xyline[nn+3] = xtop - x2 ;
486 }
487 break ;
488
489 case (MRI_ROT_0+MRI_FLMADD):
490 for( nn=ii=0 ; ii < mp->nxyline ; ii++,nn+=NXY_MEMPLOT ){
491 x1 = mp->xyline[nn ] ; y1 = mp->xyline[nn+1] ;
492 x2 = mp->xyline[nn+2] ; y2 = mp->xyline[nn+3] ;
493 thc = (int)mp->xyline[nn+5] ; if( thc == -THCODE_OPAC ) continue ;
494 mp->xyline[nn ] = xtop - x1 ;
495 mp->xyline[nn+1] = y1 ; if( thc == -THCODE_CIRC || thc == -THCODE_BALL ) continue ;
496 mp->xyline[nn+2] = xtop - x2 ;
497 mp->xyline[nn+3] = y2 ;
498 }
499 break ;
500
501 case (MRI_ROT_90+MRI_FLMADD):
502 for( nn=ii=0 ; ii < mp->nxyline ; ii++,nn+=NXY_MEMPLOT ){
503 x1 = mp->xyline[nn ] ; y1 = mp->xyline[nn+1] ;
504 x2 = mp->xyline[nn+2] ; y2 = mp->xyline[nn+3] ;
505 thc = (int)mp->xyline[nn+5] ; if( thc == -THCODE_OPAC ) continue ;
506 mp->xyline[nn ] = y1 ;
507 mp->xyline[nn+1] = x1 ; if( thc == -THCODE_CIRC || thc == -THCODE_BALL ) continue ;
508 mp->xyline[nn+2] = y2 ;
509 mp->xyline[nn+3] = x2 ;
510 }
511 break ;
512
513 case (MRI_ROT_180+MRI_FLMADD):
514 for( nn=ii=0 ; ii < mp->nxyline ; ii++,nn+=NXY_MEMPLOT ){
515 x1 = mp->xyline[nn ] ; y1 = mp->xyline[nn+1] ;
516 x2 = mp->xyline[nn+2] ; y2 = mp->xyline[nn+3] ;
517 thc = (int)mp->xyline[nn+5] ; if( thc == -THCODE_OPAC ) continue ;
518 mp->xyline[nn ] = x1 ;
519 mp->xyline[nn+1] = ytop - y1 ; if( thc == -THCODE_CIRC || thc == -THCODE_BALL ) continue ;
520 mp->xyline[nn+2] = x2 ;
521 mp->xyline[nn+3] = ytop - y2 ;
522 }
523 break ;
524
525 case (MRI_ROT_270+MRI_FLMADD):
526 for( nn=ii=0 ; ii < mp->nxyline ; ii++,nn+=NXY_MEMPLOT ){
527 x1 = mp->xyline[nn ] ; y1 = mp->xyline[nn+1] ;
528 x2 = mp->xyline[nn+2] ; y2 = mp->xyline[nn+3] ;
529 thc = (int)mp->xyline[nn+5] ; if( thc == -THCODE_OPAC ) continue ;
530 mp->xyline[nn ] = ytop - y1 ;
531 mp->xyline[nn+1] = xtop - x1 ; if( thc == -THCODE_CIRC || thc == -THCODE_BALL ) continue ;
532 mp->xyline[nn+2] = ytop - y2 ;
533 mp->xyline[nn+3] = xtop - x2 ;
534 }
535 break ;
536 }
537
538 return ;
539 }
540
541 /*---------------------------------------------------------------------------
542 Set the insertion point for over-writing -- 15 Nov 2001
543 -----------------------------------------------------------------------------*/
544
insert_at_memplot(int ii,MEM_plotdata * mp)545 void insert_at_memplot( int ii , MEM_plotdata *mp )
546 {
547 if( mp != NULL ) mp->insert_at = ii ;
548 return ;
549 }
550
551 /*---------------------------------------------------------------------------
552 Cut lines nbot..ntop out of a memplot -- 15 Nov 2001
553 -----------------------------------------------------------------------------*/
554
cutlines_memplot(int nbot,int ntop,MEM_plotdata * mp)555 void cutlines_memplot( int nbot , int ntop , MEM_plotdata *mp )
556 {
557 if( mp == NULL ) return ; /* bad or meaningless stuff */
558 if( nbot < 0 ) return ;
559 if( ntop >= mp->nxyline ) return ;
560 if( nbot > ntop ) return ;
561
562 if( ntop == mp->nxyline-1 ){ /* just set num lines to nbot */
563
564 mp->nxyline = nbot ;
565
566 } else { /* must move things above ntop down */
567
568 memmove( mp->xyline + NXY_MEMPLOT*nbot ,
569 mp->xyline + NXY_MEMPLOT*(ntop+1) ,
570 sizeof(float)*NXY_MEMPLOT*(mp->nxyline-1-ntop) ) ;
571
572 mp->nxyline -= (ntop-nbot+1) ;
573
574 }
575 return ;
576 }
577
578 /*----------------------------------------------------------------------------*/
579
580 #undef INLINE
581 #ifdef __GNUC__
582 # define INLINE inline
583 #else
584 # define INLINE /*nada*/
585 #endif
586
587 /*----------------------------------------------------------------------------
588 Clip a line to a rectangle. Return is -1 if the line is totally outside.
589 Otherwise, return is 0 and *x1in (etc.) is altered to the clipped line.
590 ------------------------------------------------------------------------------*/
591
clip_line_to_rect(float xclbot,float yclbot,float xcltop,float ycltop,float * x1in,float * y1in,float * x2in,float * y2in)592 static INLINE int clip_line_to_rect( float xclbot , float yclbot ,
593 float xcltop , float ycltop ,
594 float *x1in , float *y1in ,
595 float *x2in , float *y2in )
596 {
597 float x1=*x1in , y1=*y1in , x2=*x2in , y2=*y2in , dx,dy,slope,temp ;
598 int inter=0 ;
599
600 /* Make sure that x1 < x2 by interchanging the points if necessary */
601
602 if( x1 > x2 ){
603 temp=x1 ; x1=x2 ; x2=temp;
604 temp=y1 ; y1=y2 ; y2=temp; inter=1 ;
605 }
606
607 /* if outside entire region, throw line away */
608
609 if( x2 < xclbot || x1 > xcltop ) return -1;
610
611 if( y1 < y2 ){
612 if( y2 < yclbot || y1 > ycltop ) return -1;
613 } else {
614 if( y1 < yclbot || y2 > ycltop ) return -1;
615 }
616
617 /* if inside entire region, then do nothing */
618
619 if( x1 >= xclbot && x2 <= xcltop ){
620 if( y1 < y2 ){
621 if( y1 >= yclbot && y2 <= ycltop ) return 0 ;
622 } else {
623 if( y2 >= yclbot && y1 <= ycltop ) return 0 ;
624 }
625 }
626
627 /* Clip line in X direction */
628
629 dx = x2 - x1 ;
630 if( dx > 0.0 ){ /* only clip if line has some x range */
631 slope = (y2-y1)/dx ;
632 if( x1 < xclbot ){ /* intercept of line at left side */
633 y1 = y1 + slope*(xclbot-x1) ;
634 x1 = xclbot ;
635 }
636 if( x2 > xcltop ){ /* intercept at right */
637 y2 = y2 + slope*(xcltop-x2) ;
638 x2 = xcltop ;
639 }
640 }
641
642 /* Check line again to see if it falls outside of plot region */
643
644 if( y1 < y2 ){
645 if( y2 < yclbot || y1 > ycltop ) return -1;
646 } else {
647 if( y1 < yclbot || y2 > ycltop ) return -1;
648
649 temp=x1 ; x1=x2 ; x2=temp; /* make sure y1 <= y2 */
650 temp=y1 ; y1=y2 ; y2=temp; inter=!inter ;
651 }
652
653 /* Clip y-direction. To do this, must have y1 <= y2 [supra] */
654
655 dy = y2 - y1 ;
656 if( dy > 0.0 ){ /* only clip if line has some Y range */
657 slope = (x2-x1)/dy ;
658 if( y1 < yclbot ){ /* intercept of line at bottom */
659 x1 = x1 + slope*(yclbot-y1) ;
660 y1 = yclbot ;
661 }
662 if( y2 > ycltop ){ /* intercept at top */
663 x2 = x2 + slope*(ycltop-y2) ;
664 y2 = ycltop ;
665 }
666 }
667
668 /* Line is now guaranteed to be totally inside the plot region.
669 Copy local clipped coordinates to output values and return.
670 Note that we must restore points to original input order,
671 if they were interchanged at some point above. */
672
673 if( inter ){
674 *x1in = x2 ; *x2in = x1 ; *y1in = y2 ; *y2in = y1 ;
675 } else {
676 *x1in = x1 ; *y1in = y1 ; *x2in = x2 ; *y2in = y2 ;
677 }
678
679 return 0 ;
680 }
681
682 #undef INSIDE
683 #define INSIDE(x,y) \
684 ( (x) >= xclbot && (x) <= xcltop && (y) >= yclbot && (y) <= ycltop )
685
686 /*---------------------------------------------------------------------------
687 Clip a memplot to a rectangle, producing a new memplot.
688 -----------------------------------------------------------------------------*/
689
clip_memplot(float xclbot,float yclbot,float xcltop,float ycltop,MEM_plotdata * mp)690 MEM_plotdata * clip_memplot( float xclbot, float yclbot,
691 float xcltop, float ycltop , MEM_plotdata *mp )
692 {
693 MEM_plotdata *np ;
694 char str[256] ;
695 int nn , ii , qq ;
696 float x1,y1 , x2,y2 , col,th ;
697
698 if( mp == NULL ) return NULL ; /* bad or meaningless stuff */
699 if( xclbot >= xcltop ) return NULL ;
700 if( yclbot >= ycltop ) return NULL ;
701
702 sprintf(str,"%.240sCopy",mp->ident) ;
703 nn = create_memplot_surely( str , mp->aspect ) ;
704 np = find_memplot(NULL) ;
705 if( np == NULL ) return NULL ; /* shouldn't happen */
706
707 for( nn=ii=0 ; ii < mp->nxyline ; ii++,nn+=NXY_MEMPLOT ){
708 x1 = mp->xyline[nn ] ; y1 = mp->xyline[nn+1] ;
709 x2 = mp->xyline[nn+2] ; y2 = mp->xyline[nn+3] ;
710 col= mp->xyline[nn+4] ; th = mp->xyline[nn+5] ;
711
712 if( th < 0.0 ){ /** Not a line! */
713 int thc = (int)(-th) ;
714 switch( thc ){
715 case THCODE_RECT: /* rectangle */
716 /* both corners inside */
717 if( INSIDE(x1,y1) && INSIDE(x2,y2) ){
718 ADDTO_MEMPLOT(np,x1,y1,x2,y2,col,th) ;
719 }
720 break ;
721
722 case THCODE_BALL:
723 case THCODE_CIRC:{ /* circle */
724 /* +/- 1 radius inside */
725 float xx,yy , rr=x2 ;
726 xx = x1+rr ; if( !INSIDE(xx,y1) ) break ;
727 xx = x1-rr ; if( !INSIDE(xx,y1) ) break ;
728 yy = y1+rr ; if( !INSIDE(x1,yy) ) break ;
729 yy = y1-rr ; if( !INSIDE(x1,yy) ) break ;
730 ADDTO_MEMPLOT(np,x1,y1,x2,y2,col,th) ;
731 }
732 break ;
733
734 case THCODE_OPAC:{
735 ADDTO_MEMPLOT(np,x1,0.0f,0.0f,0.0f,col,th) ;
736 }
737 break ;
738 }
739
740 } else { /** Truly a line! **/
741
742 qq = clip_line_to_rect( xclbot,yclbot , xcltop,ycltop ,
743 &x1,&y1 , &x2,&y2 ) ;
744 if( qq == 0 ){
745 ADDTO_MEMPLOT(np,x1,y1,x2,y2,col,th) ;
746 }
747 }
748 }
749
750 if( np->nxyline == 0 ) DESTROY_MEMPLOT(np) ;
751
752 return np ;
753 }
754
755 /****************************************************************************
756 Functions to interface with PLOTPAK Fortran routines
757 *****************************************************************************/
758
759 /*-------------------------------
760 Has no function at this time.
761 ---------------------------------*/
plotpak_frame(void)762 void plotpak_frame(void) { frame_() ; }
763
764 /*-----------------------------------------------
765 Draws a sequence of lines in one swell foop.
766 -------------------------------------------------*/
plotpak_curve(float * x,float * y,int n)767 void plotpak_curve( float * x , float * y , int n )
768 {
769 integer nn = n ;
770 curve_( (real *) x , (real *) y , &nn ) ;
771 }
772
773 /*---------------------------------------------------
774 Establishes first point of a series of lines
775 to be drawn one at time using plotpak_vector.
776 -----------------------------------------------------*/
plotpak_frstpt(float x,float y)777 void plotpak_frstpt( float x , float y )
778 {
779 real xx = x , yy = y ;
780 frstpt_( &xx , &yy ) ;
781 }
782
783 /*---------------------------------------------------
784 Draws next in the series of lines.
785 -----------------------------------------------------*/
plotpak_vector(float x,float y)786 void plotpak_vector( float x , float y )
787 {
788 real xx=x , yy=y ;
789 vector_( &xx , &yy ) ;
790 }
791
792 /*-------------------
793 Draws one line.
794 ---------------------*/
plotpak_line(float x1,float y1,float x2,float y2)795 void plotpak_line( float x1 , float y1 , float x2 , float y2 )
796 {
797 real xx1 = x1 , yy1 = y1 , xx2 = x2 , yy2 = y2 ;
798 line_(&xx1, &yy1, &xx2, &yy2);
799 }
800
801 /*--------------------------------------------------------------
802 Converts (x1,y1) from user to memplot coordinates - 20 Nov 2001
803 ----------------------------------------------------------------*/
804
plotpak_zzphys(float x1,float y1,float * x2,float * y2)805 void plotpak_zzphys( float x1 , float y1 , float *x2 , float *y2 )
806 {
807 real xx1 = x1 , yy1 = y1 ;
808 zzphys_( &xx1 , &yy1 ) ;
809 if( x2 != NULL ) *x2 = xx1 ;
810 if( y2 != NULL ) *y2 = yy1 ;
811 }
812
813 /*--------------------------------------------------------------
814 Converts (x1,y1) from memplot to user coordinates - 20 Nov 2001
815 ----------------------------------------------------------------*/
816
plotpak_unphys(float x1,float y1,float * x2,float * y2)817 void plotpak_unphys( float x1 , float y1 , float *x2 , float *y2 )
818 {
819 double rr ;
820 if( x2 != NULL ){
821 rr = (x1 - zzzplt_.betaxx) / zzzplt_.alphxx ;
822 if( zzzplt_.ixcoor < 0 ) rr = pow(10.0,rr) ;
823 *x2 = rr ;
824 }
825 if( y2 != NULL ){
826 rr = (y1 - zzzplt_.betayy) / zzzplt_.alphyy ;
827 if( zzzplt_.iycoor < 0 ) rr = pow(10.0,rr) ;
828 *y2 = rr ;
829 }
830 }
831
832 /*-----------------------------------------------------------------------------
833 Establishes relationship between objective (memplot) coordinates
834 (x range is from 0 to aspect, y from 0 to 1.0) and subjective (user)
835 coordinates. The range xs1..xs2 is mapped onto xo1..xo2, and similarly
836 for y. "code" establishes the form of the mapping:
837 code = 1 => x linear, y linear
838 code = 2 => x linear, y logarithmic
839 code = 3 => x log , y linear
840 code = 4 => x log , y log
841 -------------------------------------------------------------------------------*/
plotpak_set(float xo1,float xo2,float yo1,float yo2,float xs1,float xs2,float ys1,float ys2,int code)842 void plotpak_set( float xo1,float xo2 , float yo1,float yo2 ,
843 float xs1,float xs2 , float ys1,float ys2 , int code )
844 {
845 real xobj1=xo1, xobj2=xo2, yobj1=yo1, yobj2=yo2;
846 real xsub1=xs1, xsub2=xs2, ysub1=ys1, ysub2=ys2 ;
847 integer ltype = code ;
848 set_(&xobj1, &xobj2, &yobj1, &yobj2, &xsub1, &xsub2, &ysub1, &ysub2, <ype);
849 }
850
plotpak_getset(float * xo1,float * xo2,float * yo1,float * yo2,float * xs1,float * xs2,float * ys1,float * ys2)851 void plotpak_getset( float *xo1,float *xo2 , float *yo1,float *yo2 ,
852 float *xs1,float *xs2 , float *ys1,float *ys2 )
853 {
854 if( xo1 != NULL ) *xo1 = (float) zzzplt_.xbot ;
855 if( xo2 != NULL ) *xo2 = (float) zzzplt_.xtop ;
856 if( yo1 != NULL ) *yo1 = (float) zzzplt_.ybot ;
857 if( yo1 != NULL ) *yo2 = (float) zzzplt_.ytop ;
858
859 if( xs1 != NULL ) *xs1 = (float) zzzplt_.xmin ;
860 if( xs2 != NULL ) *xs2 = (float) zzzplt_.xmax ;
861 if( ys1 != NULL ) *ys1 = (float) zzzplt_.ymin ;
862 if( ys1 != NULL ) *ys2 = (float) zzzplt_.ymax ;
863
864 return ;
865 }
866
867 /*-----------------------------------------
868 Set line type: 1 = solid (default)
869 2 = long dash
870 3 = short dash
871 4 = long - short - short
872 5 = very short
873 -------------------------------------------*/
plotpak_setlin(int code)874 void plotpak_setlin( int code )
875 {
876 integer ntype=code ;
877 setlin_(&ntype);
878 }
879
880 /*------------------------------------------------
881 Set the clipping window (objective coordinates)
882 --------------------------------------------------*/
plotpak_setw(float xo1,float xo2,float yo1,float yo2)883 void plotpak_setw( float xo1,float xo2 , float yo1,float yo2 )
884 {
885 real xobj1=xo1, xobj2=xo2, yobj1=yo1, yobj2=yo2;
886 setw_( &xobj1, &xobj2, &yobj1, &yobj2 ) ;
887 }
888
889 /*------- Plotpak routines that I'm not documenting yet
890 see the .f source code, or NCAR manual, if you care -------*/
891
plotpak_setdsh(int nd,float * xd)892 void plotpak_setdsh( int nd , float * xd )
893 {
894 integer nnd = nd ;
895 setdsh_( &nnd , (real *) xd ) ;
896 }
897
plotpak_setfrm(float xo1,float xo2,float yo1,float yo2)898 void plotpak_setfrm( float xo1,float xo2 , float yo1,float yo2 )
899 {
900 real xobj1=xo1, xobj2=xo2, yobj1=yo1, yobj2=yo2;
901 setfrm_( &xobj1, &xobj2, &yobj1, &yobj2 ) ;
902 }
903
plotpak_phdot(float x1,float y1)904 void plotpak_phdot( float x1 , float y1 )
905 {
906 real xx1=x1 , yy1=y1 ;
907 phdot_(&xx1,&yy1);
908 }
909
plotpak_phline(float x1,float y1,float x2,float y2)910 void plotpak_phline( float x1 , float y1 , float x2 , float y2 )
911 {
912 real xx1 = x1 , yy1 = y1 , xx2 = x2 , yy2 = y2 ;
913 phline_(&xx1, &yy1, &xx2, &yy2);
914 }
915
plotpak_point(float x1,float y1)916 void plotpak_point( float x1 , float y1 )
917 {
918 real xx1=x1 , yy1=y1 ;
919 point_(&xx1,&yy1);
920 }
921
plotpak_points(float * x,float * y,int n,int ipen)922 void plotpak_points( float *x , float *y , int n , int ipen )
923 {
924 integer nn=n , nipen=ipen , zero=0 ;
925 points_( (real *)x , (real *)y , &nn , &zero , &nipen ) ;
926 }
927
928 void ppak_garbage_routine(void) ;
this_is_real_junk(void)929 void this_is_real_junk(void){ ppak_garbage_routine(); }
930