📄 xreticle.c
字号:
/* Copyright (c) 1995 Entropic Research Laboratory, Inc. *//* * This material contains unpublished, proprietary software of * Entropic Research Laboratory, Inc. Any reproduction, distribution, * or publication of this work must be authorized in writing by Entropic * Research Laboratory, Inc., and must bear the notice: * * "Copyright (c) 1987-1990 AT&T, Inc. * "Copyright (c) 1986-1990 Entropic Speech, Inc. * "Copyright (c) 1990-1993 Entropic Research Laboratory, Inc. * All rights reserved" * * The copyright notice above does not evidence any actual or intended * publication of this source code. * * Written by: * Checked by: * Revised by: * * reticle.c * procedures to plot reticles and numerics */static char *sccs_id = "@(#)xreticle.c 1.10 9/28/98 ATT/ERL";/* For spectrograms, scalar signals, Cartesian plots (linear axes):Ordinate intervals (marker intervals, marker lengths) major minor 1 minor 2 numbering interval numbering precision numbering location marking styleAbscissa intervals (marker intervals, marker lengths) major minor 1 minor 2 numbering interval numbering precision numbering location marking styleImage boundaries (in pixels; 0,0 is upper left) top (location of highest ordinate value) left (location of lowest abscissa value) bottom rightColorLine typeFontOrdinate range start endAbscissa range start endOrdinate labelAbscissa label******************************************************************/#include <stdio.h>#include <esps/esps.h>#include <Objects.h>#include <xview/font.h>#ifndef ERS#include <Xp_pw.h>#endif#define oneormore(x) (((y = (int)(x)) >= 1)? y : 1)/* char default_font[] = "/usr/lib/fonts/fixedwidthfonts/serif.r.12"; */char default_x_precision[] = "%6.1lf";char default_y_precision[] = "%6.0lf";extern char *savestring();static double myfmod();static void do_x_numbers(), do_x_label(), do_y_numbers(), central_marks();static int *get_ord_marklist(), *get_absc_marklist();static void arb_spect_view_int(), lin_spect_view_int();extern int debug_level;extern Xv_Font def_font;extern int def_font_height, def_font_width;/******************************************************************/Bound *reticle_get_margins(r) Reticle *r;{ static Bound b; int height, width, maxl, i; char tmp[100], *p; if(r) { b.top = b.bottom = b.right = b.left = 1; if (!r->font) r->font = def_font; height = def_font_height; width = def_font_width; if (debug_level >= 2) fprintf(stderr, "%s: font %x width %d\n", "reticle_get_margins", r->font, width); if(r->ordinate.num_loc & NUM_BOTH) { sprintf(tmp,r->ordinate.precision,r->ordi.start); p = tmp; while(*p == ' ') p++; maxl = strlen(p); sprintf(tmp,r->ordinate.precision,r->ordi.end); p = tmp; while(*p == ' ') p++; if(strlen(p) > maxl) maxl = strlen(p); if(r->ordinate.num_loc & NUM_LB) b.left += ((1 + maxl) * width); if(r->ordinate.num_loc & NUM_RT) b.right += ((1 + maxl) * width); } if(r->abscissa.num_loc & NUM_LB) { b.bottom += (height + 1); } else if(r->ordinate.num_loc & NUM_BOTH) b.bottom += 1 + (height/2); if(r->abscissa.num_loc & NUM_RT) { b.top += (height + 1); } else if(r->ordinate.num_loc & NUM_BOTH) b.top += 1 + (height/2); if(r->abs_label) b.bottom += (height + 1); return(&b); } return(NULL);} /******************************************************************/Reticle *new_spectrogram_reticle(){ Reticle *r; if(!(r = (Reticle*)malloc(sizeof(Reticle)))) return(NULL); r->ordinate.maj.style = MAJOR | EDGES; r->ordinate.maj.length = .020; r->ordinate.maj.inter = 1000.0; r->ordinate.maj.list = NULL; r->ordinate.maj.num = 0; r->ordinate.min1.style = EDGES; r->ordinate.min1.length = .010; r->ordinate.min1.inter = 500.0; r->ordinate.min1.list = NULL; r->ordinate.min1.num = 0; r->ordinate.min2.style = EDGES; r->ordinate.min2.length = .005; r->ordinate.min2.inter = 100.0; r->ordinate.min2.list = NULL; r->ordinate.min2.num = 0; r->ordinate.precision = savestring(default_y_precision); r->ordinate.num_inter = 1000.0; r->ordinate.num_loc = NUM_LB; r->abscissa.maj.style = MAJOR | EDGES; r->abscissa.maj.length = 200.0; r->abscissa.maj.inter = .1; r->abscissa.maj.list = NULL; r->abscissa.maj.num = 0; r->abscissa.min1.style = EDGES; r->abscissa.min1.length = 100.0; r->abscissa.min1.inter = .05; r->abscissa.min1.list = NULL; r->abscissa.min1.num = 0; r->abscissa.min2.style = EDGES; r->abscissa.min2.length = 50.0; r->abscissa.min2.inter = .01; r->abscissa.min2.list = NULL; r->abscissa.min2.num = 0; r->abscissa.precision = savestring(default_x_precision); r->abscissa.num_inter = .1; r->abscissa.num_loc = NUM_LB; r->bounds.top = 1; r->bounds.bottom = 384; r->bounds.left = 1; r->bounds.right = 512; r->color = 255; r->linetype = 1; r->font = XV_NULL; r->abs_label = NULL; r->ord_label = NULL; r->ordi.start = 0.0; r->ordi.end = 5000.0; r->absc.start = 0.0; r->absc.end = 1.0; return(r);}/******************************************************************//* Find a "round" approximation to u of the form c*10^e, where the coefficient c is 1, 2, or 5, and the exponent e is an integer. Result lies between 0.63*u and 1.6*u. */doubleret_scale(u, cp, ep) double u; int *cp, *ep;{ double half_log_2 = .1505149978319905976; /* log10(2.0)/2.0 */ double t; int c, e; t = log10(u); t -= e = ROUND(t); if (t > half_log_2) c = 2; else if (t >= -half_log_2) c = 1; else { c = 5; e -= 1; } if (cp) *cp = c; if (ep) *ep = e; return c * pow(10.0, (double) e);}/******************************************************************/intscale_spect_view_ret(r, v) Reticle *r; View *v;{ double x_scl = (r->absc.end - r->absc.start) * PIX_PER_CM / (double)(r->bounds.right - r->bounds.left); double y_scl = (r->ordi.end - r->ordi.start) * PIX_PER_CM / (double)(r->bounds.bottom - r->bounds.top); double maj_len = 0.5; /* Longest ticks 0.5 cm. */ double ab_maj_int = 2.0; /* Spacing between major ticks roughly */ double ord_maj_int = 1.5; /* 2 cm horizontally and 1.5 cm vertically */ /* Give tick marks absolute length, independent of data units. */ r->ordinate.maj.length = maj_len*x_scl; r->ordinate.min1.length = r->ordinate.maj.length/2.0; r->ordinate.min2.length = r->ordinate.maj.length/4.0; r->abscissa.maj.length = maj_len*y_scl; r->abscissa.min1.length = r->abscissa.maj.length/2.0; r->abscissa.min2.length = r->abscissa.maj.length/4.0; /* Insure reasonable tick spacing. */ lin_spect_view_int(&r->abscissa, ab_maj_int*x_scl); if (v->sig && v->sig->y_dat) { ord_maj_int = 0.8; /* Closer spacing of major ticks since we don't yet do minor ticks for nonlinear y scale. */ arb_spect_view_int(&r->ordinate, ord_maj_int, r->bounds.bottom, r->bounds.top, v, v->y_to_yval, v->yval_to_y); } else lin_spect_view_int(&r->ordinate, ord_maj_int*y_scl); /* Formats for axis numbering */ reticle_set_ord_precision(r,"%g"); reticle_set_absc_precision(r,"%g"); return TRUE;}/******************************************************************/static voidlin_spect_view_int(intv, maj_int) Interval *intv; double maj_int; /* data units */{ int coef, expt; /* maj_int is desired spacing of major ticks. Actual spacing may be larger or smaller by a factor of sqrt(5.0 / 2.0) to allow finding a "round" approximation (1, 2, of 5 times pwr of 10). */ intv->maj.inter = intv->num_inter = ret_scale(maj_int, &coef, &expt); intv->min1.inter = intv->maj.inter/2.0; intv->min2.inter = intv->maj.inter/10.0; switch (coef) { case 1: break; case 2: intv->min1.length = intv->maj.length; break; case 5: intv->min1.inter = intv->maj.inter/5.0; break; }}/******************************************************************/doubleround_num_between(a, b) double a, b;{ double p, x; if (a == b) return a; if (a > b) {double t = a; a = b; b = t;} p = pow(10.0, floor(log10(b - a))); if (p > b - a) p /= 10.0; if (10*p <= b - a) p *= 10.0; x = b - fmod(b, 10*p); if (x >= a) return x; x = b - fmod(b, 5*p); if (x >= a) return x; x = b - fmod(b, 2*p); if (x >= a) return x; return b - fmod(b, p);/*!*//* Sometimes there are two equally good candidates of the form 2n.10^e. Might be good to find a way to return both. */}/******************************************************************/static voidarb_spect_view_int(intv, maj_int, lo, hi, v, to_dat, to_pix) Interval *intv; /* e.g. ordinate or abscissa of a reticle */ double maj_int; /* desired tick spacing (cm) */ int lo, hi; /* pixel boundaries (bottom & top or left & right) */ View *v; /* view---arg for to_dat & to_pix */ double (*to_dat)(); /* e.g. y_to_yval or x_to_time */ int (*to_pix)(); /* e.g. yval_to_y or time_to_x */{ int step, inc, dec; int descending = lo > hi; int tgt, min, max, loc; double val; int len; LocVal *list, *tick; /* maj_int is desired spacing of major ticks. Actual spacing may be larger or smaller by about a factor of sqrt(2.5). (Limits arbitrarily chosen to agree with lin_spect_view_int). */ maj_int *= PIX_PER_CM; if (maj_int < 2.0) maj_int = 2.0; step = ROUND(maj_int); inc = ROUND(1.58*maj_int) - step; dec = step - (2*(inc+step))/5; if (descending) { step = -step; inc = -inc; dec = -dec; } len = 1 + (hi - lo)/(step - dec); list = (intv->maj.list) ? (LocVal *) realloc((char *) intv->maj.list, sizeof(LocVal)*len) : (LocVal *) malloc(sizeof(LocVal)*len); if (!list) /* allocation error */ { intv->maj.inter = 0.0; intv->maj.list = NULL; intv->maj.num = 0; } else { /* If data interval contains 0.0, maybe better to work in both directions from there. */ tick = list; for (min = tgt = lo, max = tgt + inc; (descending) ? (max >= hi || ((max = hi), tgt >= hi)) : (max <= hi || ((max = hi), tgt <= hi)); tgt = loc + step, min = tgt - dec, max = tgt + inc) { val = round_num_between((*to_dat)(v, min), (*to_dat)(v, max)); loc = (*to_pix)(v, val); tick->loc = loc; tick->val = val; tick++; } intv->num_inter = 0.0; /* Use list of major ticks instead. */ intv->maj.list = list; intv->maj.num = tick - list; }/*!*//* Do minor ticks after we see how the major ticks work out. (Will have to add to get_*_marklist then.) */ intv->min1.list = intv->min2.list = NULL; intv->min1.num = intv->min2.num = 0; intv->min1.inter = intv->min2.inter = 0.0;}/******************************************************************/Reticle *new_wave_reticle(){ Reticle *r; if(!(r = (Reticle*)malloc(sizeof(Reticle)))) return(NULL); r->ordinate.maj.style = MAJOR | EDGES; r->ordinate.maj.inter = 32768.0; r->ordinate.maj.list = NULL; r->ordinate.maj.num = 0; r->ordinate.min1.style = EDGES | MAJOR; r->ordinate.min1.length = .01; r->ordinate.min1.inter = 4096.0; r->ordinate.min1.list = NULL; r->ordinate.min1.num = 0; r->ordinate.min2.style = EDGES ; r->ordinate.min2.length = .005; r->ordinate.min2.inter = 512.0; r->ordinate.min2.list = NULL; r->ordinate.min2.num = 0; r->ordinate.precision = savestring(default_y_precision); r->ordinate.num_inter = 8192.0; r->ordinate.num_loc = NUM_LB; r->abscissa.maj.style = MINOR1 | EDGES; r->abscissa.maj.length = 1024.0; r->abscissa.maj.inter = .1; r->abscissa.maj.list = NULL; r->abscissa.maj.num = 0; r->ordinate.maj.length = r->abscissa.maj.inter; r->abscissa.min1.style = EDGES; r->abscissa.min1.length = 512.0; r->abscissa.min1.inter = .05; r->abscissa.min1.list = NULL; r->abscissa.min1.num = 0; r->abscissa.min2.style = EDGES; r->abscissa.min2.length = 256.0; r->abscissa.min2.inter = .01; r->abscissa.min2.list = NULL; r->abscissa.min2.num = 0; r->abscissa.precision = savestring(default_x_precision); r->abscissa.num_inter = .1; r->abscissa.num_loc = NUM_LB; r->bounds.top = 1; r->bounds.bottom = 384; r->bounds.left = 1; r->bounds.right = 512; r->color = 255; r->linetype = 1; r->font = XV_NULL; r->abs_label = NULL; r->ord_label = NULL; r->ordi.start = -16384.0; r->ordi.end = 16384.0; r->absc.start = 0.0; r->absc.end = 1.5; return(r);}/******************************************************************//* Cf. free_ret in libsig/signal.c. */voidfree_reticle(r) Reticle *r;{ if (r) { if (r->abs_label) free(r->abs_label); if (r->ord_label) free(r->ord_label); if(r->abscissa.precision) free(r->abscissa.precision); if(r->ordinate.precision) free(r->ordinate.precision); if (r->ordinate.maj.list) free(r->ordinate.maj.list); if (r->ordinate.min1.list) free(r->ordinate.min1.list); if (r->ordinate.min2.list) free(r->ordinate.min2.list); if (r->abscissa.maj.list) free(r->abscissa.maj.list); if (r->abscissa.min1.list) free(r->abscissa.min1.list); if (r->abscissa.min2.list) free(r->abscissa.min2.list); free(r); }}/******************************************************************/static double myfmod(num,den) register double num, den;{ register int q; register double dq; dq = num/den; q = dq; if(dq >= 0.0) { if((dq - ((double)q)) > .99999) q++; return( num - ((double)q)*den); } else { if((((double)q) - dq) > .99999) q--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -