📄 view_utils.c
字号:
if (val < v->sig->smin[chan]) val = v->sig->smin[chan]; else if (val > v->sig->smax[chan]) val = v->sig->smax[chan]; for(i=0; i < v->dims; i++) if(v->elements[i] == chan) { val *= PIX_PER_CM / (v->y_scale[i]); return(v->y_offset[i] - ROUND(val)); }}/*********************************************************************/#define DIST(d) \ ((!(d)) ? -1 : \ iabs(y - (v->y_offset[i] - (int)((d)[ind]*PIX_PER_CM/v->y_scale[i]))))generic_xy_to_chan(v,x,y) register View *v; int x, y;{ register Signal *s; if(v && (s = v->sig)) { if(v->dims == 1) return(v->elements[0]); /* special-case for speed */ else { int i, mini, mind, j, ind; double time = (v->x_to_time)? v->x_to_time(v, x) : generic_x_to_time(v, x); if (!s->data) { fprintf(stderr, "NULL signal data array in generic_xy_to_chan.\n"); return 0; } ind = time_to_index(s, time); mind = 5000; /* needs to be bigger than biggest y screen in pixels */ mini = 0; for (i = 0; i < v->dims; i++) { switch(s->type & VECTOR_SIGNALS) { case P_SHORTS: j = DIST(((short**)(s->data))[v->elements[i]]); break; case P_DOUBLES: j = DIST(((double**)(s->data))[v->elements[i]]); break; case P_FLOATS: j = DIST(((float**)(s->data))[v->elements[i]]); break; case P_INTS: j = DIST(((int**)(s->data))[v->elements[i]]); break; case P_CHARS: j = DIST(((char**)(s->data))[v->elements[i]]); break; case P_MIXED: { caddr_t s_data; if(! s->types) { fprintf(stderr, "s->types null for P_MIXED in generic_xy_to_chan\n"); return(0); } s_data = ((caddr_t *) s->data)[v->elements[i]]; switch (s->types[v->elements[i]]) { case P_SHORTS: j = DIST((short *) s_data); break; case P_DOUBLES: j = DIST((double *) s_data); break; case P_FLOATS: j = DIST((float *) s_data); break; case P_INTS: j = DIST((int *) s_data); break; case P_CHARS: j = DIST((char *) s_data); break; } } break; }#undef DIST(d) if (j < 0) { fprintf(stderr, "NULL signal data in generic_xy_to_chan.\n"); return 0; } else if (j < mind) { mind = j; mini = i; } } return(v->elements[mini]); } } if(debug_level) fprintf(stderr,"Bad args to generic_xy_to_chan %x\n", v); return(0);} /*********************************************************************/plot_view(v) View *v;{ Frame fr; if(v->canvas && (fr = (Frame)xv_get(v->canvas,XV_OWNER)) && !xv_get(fr, FRAME_CLOSED)) { if (v->set_scale) v->set_scale(v); if (v->data_plot) { v->data_plot(v); v->plotted = TRUE; } if (v->reticle_plot) v->reticle_plot(v); if (v->x_print) v->x_print(v); if (v->y_print) v->y_print(v); if (v->cursor_plot) { v->cursor_plot(v,CURSOR_COLOR); /* do frequent x-or ops last */ view_xor_marks(v); } if (v->vmarker_plot) v->vmarker_plot(v,2); if (v->hmarker_plot) v->hmarker_plot(v,2); /* update scrollbar for new configuration */ set_scrollbar(v); plot_scrollbar(v->scrollbar); }}/*********************************************************************//* Search for view referring to a signal, not necessarily on signal's * own view list (e.g. overlays). */View *find_view(sig) Signal *sig;{ Object *o; Signal *s; View *v; if (sig->views) return sig->views; else if ((o = (Object *) sig->obj)) for (s = o->signals; s; s = s->others) for (v = s->views; v; v = v->next) if (v->sig == sig) return v; return NULL;}/*********************************************************************//* Get a segment of signal. Adjust view start and end times to matchsegment actually obtained. Return TRUE if the viewable segmentactually changed (i.e. if redisplay is necessary). Clip start andpage_time, if necessary. */#define FUZZ 0.000001get_view_segment(view, start, page_time) register View *view; register double *start, *page_time;{ double end, resolution; int wasopen, redo; double buf_start, buf_end; end = *start + *page_time; redo = FALSE; resolution = *view->x_scale/PIX_PER_CM; /* display time resolution per pixel */ /* Clip requested interval to lie within the signal. */ if (*start < view->sig->start_time) { /* does this seem clumsey? */ *start = view->sig->start_time; end = *start + *page_time; } if (end > SIG_END_TIME(view->sig)) { end = SIG_END_TIME(view->sig); *start = end - *page_time; } if (*start < view->sig->start_time) /* must duration be clipped? */ *start = view->sig->start_time; *page_time = end - *start; /* return corrected page time */ while(view) { if((SIG_END_TIME(view->sig) > *start) && (view->sig->start_time < end)) { /* If either view->start_time or ET(view) changes, redisplay must be done. */ if(view->start_time != *start) { if((view->sig->freq == 0.0) || ((view->sig->freq > 0.0) && (fabs(*start - view->start_time) >= resolution))) redo = TRUE; view->start_time = *start; } if((ET(view) != end) && ((view->sig->freq == 0.0) || ((view->sig->freq > 0.0) && (fabs(ET(view) - end) >= resolution)))) { redo = TRUE; } /* if region not already in buffer, read data from file */ buf_start = BUF_START_TIME(view->sig); buf_end = BUF_END_TIME(view->sig); if ((view->sig->file != SIG_NEW) && (*start < buf_start - fabs(FUZZ*buf_start) || end > buf_end + fabs(FUZZ*buf_end))) { wasopen = (view->sig->file >= 0); view->sig->utils->read_data(view->sig, *start, end - *start); if (view->sig->buff_size == 0) { sprintf(notice_msg, "%s: No records read (requested segment length %g sec).\n", "get_view_segment", end - *start); show_notice(1,notice_msg); } if(!wasopen) close_sig_file(view->sig); if((view->sig->type & SPECIAL_SIGNALS) != SIG_SPECTROGRAM) /* for speed... */ get_maxmin(view->sig); redo = TRUE; } } view = view->next; } return(redo); /* return "redisplay is required" boolean */}#undef FUZZ/*********************************************************************/view_fit_duration(v) View* v;{ if(v && v->canvas && v->sig) { double page_time = ((double)(v->sig->buff_size))/v->sig->freq; *(v->x_scale) = PIX_PER_CM * page_time / (v->width - *(v->x_offset)); }}/*********************************************************************/position_view(view,start,end) View *view; double start, end;{ double page_time; page_time = end - start; if (start >= end) return; get_view_segment(view, &start, &page_time); *(view->x_scale) = PIX_PER_CM * page_time / (view->width - *(view->x_offset)); redoit(view->canvas);}/*********************************************************************/page(view,sig,start) View *view; Signal *sig; double start;{ double page_time; Signal *sig0 = sig; extern int scroll_ganged; page_time = ET(view) - view->start_time; if(get_view_segment(view, &start, &page_time)) redoit(view->canvas); if(scroll_ganged) { sig = ((Object*)sig0->obj)->signals; while(sig) { if((sig0 != sig) && (view = sig->views)) { start = sig0->views->start_time; /* borrow new start time */ page_time = ET(view) - view->start_time; if(get_view_segment(view,&start,&page_time)) redoit(view->canvas); } sig = sig->others; } }}/*********************************************************************/voidzoom_view(v, time, ratio) View *v; double time, ratio;{ Signal *s, *so; extern int zoom_ganged; double ptime; /* start time & page duration */ double start; extern int h_spect_rescale; /* current time (e.g. of cursor) remains fixed; endpoints float */ if (!v || !(s = v->sig)) return; if (v->h_rescale) { start = time - (time - v->start_time)*ratio; ptime = (ET(v) - v->start_time)*ratio; if(get_view_segment(v, &start, &ptime)) { *(v->x_scale) = PIX_PER_CM * ptime / (v->width - *(v->x_offset)); redoit(v->canvas); } } if(zoom_ganged) /* zoom all the other views in the object (if possible) */ zoom_others(s, *(v->x_scale), v->start_time, ET(v));}/*************************************************************************/zoom_others(s, x_scale, startr, endr) Signal *s; double x_scale, startr, endr;{ Signal *so; View *view; double ptime, start, end; extern int h_spect_rescale; so = ((Object*)s->obj)->signals; while(so) { if((so != s) && (view = so->views)) { start = startr; /* borrow new start time and scale*/ ptime = x_scale * (view->width - *(view->x_offset))/PIX_PER_CM; if (view->h_rescale) { get_view_segment(view, &start, &ptime); *(view->x_scale) = PIX_PER_CM * ptime / (view->width - *(view->x_offset)); redoit(view->canvas); } else { if(((start < view->start_time) && (start >= so->start_time)) || (((end = start + ptime) > endr) && (end <= so->end_time))) { /* should use SIG_END_TIME() */ if(get_view_segment(view, &start, &ptime)) redoit(view->canvas); } } } so = so->others; }}/*********************************************************************/do_align_views(obj, v) Object *obj; View *v;{ Signal *s; View *view_to_match = v; int maxoff; struct rect r; Frame frm; /* See if the view needs to be moved to accommodate views with greater x_offset. */ for (s = obj->signals, maxoff = *v->x_offset; s; s = s->others) if ((v = s->views) && (v->start_time < ET(view_to_match)) && (ET(v) > view_to_match->start_time)) if (*v->x_offset > maxoff) maxoff = *v->x_offset; frm = (Frame) xv_get(view_to_match->canvas, XV_OWNER); frame_get_rect(frm,&r); maxoff += WMGR_MARGIN - r.r_left - *view_to_match->x_offset;/*!*//* DEBUG */ if (debug_level >= 2) fprintf(stderr, "do_align_views: r_top %d\tr_left %d\tr_width %d\tr_height %d.\n", r.r_top, r.r_left, r.r_width, r.r_height); if (maxoff > 0) { int trim; trim = r.r_left + maxoff + r.r_width + WMGR_MARGIN - SCREEN_WIDTH; if (trim < 0) trim = 0; /* The align_view's in the loop below are (or may be) done before the resize triggered by the xv_set, and align_view refers to the width of the model view. So set this value now. */ view_to_match->width = r.r_width - trim - 2*FRAME_MARGIN; xv_set(frm, XV_X, r.r_left + maxoff, XV_WIDTH, r.r_width - trim, 0); } for (s = obj->signals; s; s = s->others) for (v = s->views; v; v = v->next) if (v != view_to_match) align_view(v,view_to_match);}/*********************************************************************/align_view(v, vmodel) View *v, *vmodel;{ /* Goal: change screen location, x-scale and view times so that the curor in * ``v'' is horizontally aligned on the screen with the cursor in the model. * The window will be narrowed if required by scale and signal end time. */ /* There are two major cases: views that can change horizontal scale, and those that can't. */ Signal *s = v->sig; Frame frm = (Frame)xv_get(v->canvas,XV_OWNER); Frame frmmodel = (Frame)xv_get(vmodel->canvas,XV_OWNER); extern int h_spect_rescale; struct rect r; double x_scale = PIX_PER_CM / (*vmodel->x_scale); /* pixels/sec */ double dt, start, page, end; int x_scalable = v->h_rescale; int offset = *v->x_offset, m_left, m_right, x_loc, x_end, v_left, gotnew, v_width;#define ET_PROPOSED(v) \ ((v)->start_time + (*(v)->x_scale * \ (x_end - x_loc - 2*FRAME_MARGIN - *(v)->x_offset) / PIX_PER_CM)) if((end = ET(vmodel)) > BUF_END_TIME(vmodel->sig)) end = BUF_END_TIME(vmodel->sig); start = vmodel->start_time; page = end - start; /* check for temporal overlap of signals. */ if (v->extra_type == VIEW_OVERLAY || s->start_time > end || SIG_END_TIME(s) < start) return(TRUE); /* Views have nothing in common! */ /* Get screen location and width of model and ancillary views. */ frame_get_rect(frmmodel, &r); m_left = r.r_left; /* right and left model bounds */ m_right = m_left + r.r_width; frame_get_rect(frm, &r); v_left = r.r_left; /* current right and left view bounds */ v_width = r.r_width; x_loc = m_left + *vmodel->x_offset - *v->x_offset; /* need to move here */ x_end = m_right; /* assumes zero-width rh border */ if(! x_scalable) { /* spectrogram (or other unscalable view)? */ if((start < v->start_time) || (end > ET(v))) /* If it's all on screen, don't scroll */ gotnew = get_view_segment(v,&start,&page); else gotnew = FALSE; /* Window of ancillary view is moved only if necessary to align its left edge or BUF_START or BUF_END with model: */ if((dt = start - vmodel->start_time) > 0.0) x_loc += (0.5 + (dt * x_scale)); /* match left edges (starting times) */ if((end > BUF_END_TIME(s)) || (ET_PROPOSED(v) > BUF_END_TIME(s))) x_end = x_loc + (0.5 + (BUF_END_TIME(s)-start) * PIX_PER_CM/(*v->x_scale)) + *v->x_offset + 2*FRAME_MARGIN; if ((x_loc != v_left) || (x_end != v_left + v_width)) { v->start_time = start; xv_set(frm, XV_WIDTH, x_end - x_loc, XV_X, x_loc, 0); /* xv_set() forces a repaint() as part of the resize sequence ... */ } if (gotnew && x_end - x_loc == v_width) /* ... if the size changes. */ redoit(v->canvas); } else { /* view IS time-scalable */ gotnew = get_view_segment(v,&start,&page); /* Get as much as possible. */ /* Window of ancillary view is moved only if necessary to align its left edge or BUF_START or BUF_END with model: */ *v->x_scale = *vmodel->x_scale; if((dt = start - vmodel->start_time) > 0.0) x_loc += (0.5 + (dt * x_scale)); if((end > BUF_END_TIME(s)) || (ET_PROPOSED(v) > BUF_END_TIME(s))) x_end = x_loc + (0.5 + (BUF_END_TIME(s)-start) * x_scale) + *v->x_offset + 2*FRAME_MARGIN; if ((x_loc != v_left) || (x_end != v_left + v_width)) { v->start_time = start; v->width = x_end - x_loc - 2*FRAME_MARGIN; /* prevents auto-rescale */ xv_set(frm, XV_WIDTH, x_end - x_loc, XV_X, x_loc, 0); /* xv_set() forces a repaint() as part of the resize sequence ... */ } if (gotnew && x_end - x_loc == v_width) redoit(v->canvas); } return(TRUE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -