📄 hist.c
字号:
/* a little loop unrolling here, why not? */ sprintf( tmp_str, "%d %d %d %d ", point_array[i*4+0], point_array[i*4+1], point_array[i*4+2], point_array[i*4+3] ); Tcl_DStringAppend( &point_list, tmp_str, -1 ); } sprintf( tmp_str, "%d %d %d %d", point_array[i*4+0], point_array[i*4+1], point_array[i*4+2], point_array[i*4+3] ); Tcl_DStringAppend( &point_list, tmp_str, -1 ); if (!Tcl_SetVar( interp, listVarName, Tcl_DStringValue( &point_list ), TCL_LEAVE_ERR_MSG )) return TCL_ERROR; Tcl_DStringFree( &point_list ); return TCL_OK;}static int Draw( interp, hist, argc, argv )Tcl_Interp *interp;stateHist *hist;int argc;char *argv[];{ int *point_array; typedef char num_str_type[25]; num_str_type *num_str; char **call_argv; char tags[50]; int i, npoints; Tcl_CmdInfo cmd_info; /* 0 bins could cause me problems */ if (!hist->nbins) return TCL_OK; npoints = 4 * (hist->nbins + 1); point_array = (int*)malloc( sizeof(double) * npoints ); /* fill the array with point coordinates */ Pointlist( hist, point_array ); num_str = (num_str_type*)malloc( 25 * npoints ); for (i=0; i<npoints; i++) { sprintf( num_str[i], "%d", point_array[i] ); } /* create call_argv array */ call_argv = (char**)malloc( sizeof(char*) * (npoints + 9) ); /* eval $canvas create polygon $pointlist $fill_cmd $filler -tags hist */ call_argv[0] = hist->canvas; call_argv[1] = "create"; call_argv[2] = "polygon"; for (i=0; i<npoints; i++) { call_argv[i+3] = num_str[i]; } call_argv[i+3] = hist->bw ? "-stipple" : "-fill"; call_argv[i+4] = hist->bw ? hist->bitmap : hist->color; call_argv[i+5] = "-tags"; sprintf( tags, "hist color_%d", hist->state_no ); call_argv[i+6] = tags; call_argv[i+7] = 0; call_argv[i+8] = 0; Tcl_GetCommandInfo( interp, hist->canvas, &cmd_info ); Tcl_CallArgv( cmd_info, interp, i+7, call_argv ); call_argv[2] = "line"; call_argv[7] = "-fill"; call_argv[8] = hist->outlineColor; call_argv[9] = "-tags"; call_argv[10] = "hist color_fg"; call_argv[11] = call_argv[12] = 0; for (i=0; i<npoints-2; i+=2) { call_argv[3] = num_str[i]; call_argv[4] = num_str[i+1]; call_argv[5] = num_str[i+2]; call_argv[6] = num_str[i+3]; Tcl_CallArgv( cmd_info, interp, 11, call_argv ); } call_argv[3] = num_str[i]; call_argv[4] = num_str[i+1]; call_argv[5] = num_str[0]; call_argv[6] = num_str[1]; Tcl_CallArgv( cmd_info, interp, 11, call_argv ); free( (char*)call_argv ); return TCL_OK;}/* point_list will be filled with 4*(hist->nbins + 1) coordinates */static int Pointlist( hist, point_list )stateHist *hist;int *point_list;{ int i, tallest_bin; int *bins; double hscale, vscale; double this_height, last_height; /* zero bins could mess stuff up */ if (!hist->nbins) return TCL_OK; /* if we're computing the same as before, don't compute */ if (hist->last_bins && hist->last_nbins == hist->nbins && hist->last_left == hist->left && hist->last_right == hist->right) { bins = hist->last_bins; hist->last_bins = 0; /* don't worry, we'll put the pointer back when we're done */ } else { if (hist->last_bins) free( (char*)hist->last_bins ); /* create array for all the bin sizes */ bins = (int*)malloc( sizeof(int) * hist->nbins ); /* split the data into the bins */ State_HistBins( hist, hist->left, hist->right, bins, hist->nbins ); } /* pick out tallest bin */ tallest_bin = bins[0]; for (i=0; i<hist->nbins; i++) { if (bins[i] > tallest_bin) tallest_bin = bins[i]; } if (!tallest_bin) tallest_bin = 1; /* If maxbin is nonpositive, it is a percentage telling how much of the vertical height of the window should be filled with the tallest bin. */ if (hist->maxbin <= 0) { vscale = (-hist->maxbin) / (100 * tallest_bin) * hist->height; } else { vscale = (double)hist->height / hist->maxbin; } hscale = (double)hist->width / hist->nbins; last_height = 0; /* build each point of the histogram *//* 1----2 | | | | 5----6 | | | | | 3----4 | | | 0 7*/ for (i=0; i<hist->nbins; i++) { this_height = bins[i] * vscale; /* if the bin has anything in it, make it at least show */ if (this_height < 1 && bins[i] != 0) this_height = 1.0; point_list[i*4+0] = i*hscale; point_list[i*4+1] = hist->height - last_height; point_list[i*4+2] = i*hscale; point_list[i*4+3] = hist->height - this_height; last_height = this_height; } point_list[i*4+0] = hist->width; point_list[i*4+1] = hist->height - this_height; point_list[i*4+2] = hist->width; point_list[i*4+3] = hist->height; /* save it. Free it next time if you have to. */ hist->last_bins = bins; hist->last_nbins = hist->nbins; hist->last_left = hist->left; hist->last_right = hist->right; return TCL_OK;}static stateHist *HistToken2Ptr( interp, token )Tcl_Interp *interp;char *token;{ stateHist *hist; int ptr_no; /* the token will be of the form hist32, or hist19, or whatever */ if (!(sscanf( token, "hist%d", &ptr_no )) || !(hist = GetTclPtr( ptr_no ))) { Tcl_AppendResult( interp, token, " -- unrecognized histogram token", (char*)0 ); return 0; } else { return hist; }}static int CompareLen( va, vb )#if !(defined(sparc) || defined(hpux)) || defined(__STDC__)const#endifvoid *va, *vb;{ return (*(double*)va > *(double*)vb) ? 1 : -1;}static int State_HistBins( hist, shortLen, longLen, bins, nbins )stateHist *hist;double shortLen, longLen;int *bins, nbins;{ int i, bin_no; double binLen; /* length of each bin; how wide a range */ /* of seconds each bin covers */ double nextBin; /* start of the next bin */ double *lenptr; /* where we are in the BIG LIST */ if (!hist->n) { for (i=0; i<nbins; i++) bins[i] = 0; hist->vis_n = 0; hist->vis_sum = 0; hist->vis_average = 0; hist->vis_std_dev = 0; hist->vis_shortest = 0; hist->vis_longest = 0; return 0; } /* use the latest firstIdx if it's valid */ /* find first length */ if (shortLen == hist->shortLen) { i = hist->firstIdx; } else { i = BsearchGE( hist, shortLen, 0, hist->n - 1 ); hist->shortLen = shortLen; hist->firstIdx = i; } binLen = (longLen - shortLen) / nbins; nextBin = shortLen + binLen; bin_no = 0; lenptr = hist->lens + i; Stats_Reset( hist->vis_stats ); bins[0] = 0; for (; i < hist->n && *lenptr <= longLen; i++, lenptr++) { /* don't want to go past the last bin */ /* skip until the bin for this guy is found */ while (bin_no < nbins-1 && *lenptr > nextBin) { bin_no++; bins[bin_no] = 0; nextBin += binLen; } Stats_Add( hist->vis_stats, *lenptr ); bins[bin_no]++; } /* fill remaining bins with 0 */ while (++bin_no < nbins) { bins[bin_no] = 0; } hist->vis_n = Stats_N( hist->vis_stats ); hist->vis_sum = Stats_Sum( hist->vis_stats ); hist->vis_average = Stats_Av( hist->vis_stats ); hist->vis_std_dev = Stats_StdDev( hist->vis_stats ); hist->vis_shortest = Stats_Min( hist->vis_stats ); hist->vis_longest = Stats_Max( hist->vis_stats );#if 0 while (bin_no < nbins-1) { /* get the index of the last length contained in this bin */ bins[bin_no] = binEnd - i; /* fprintf( stderr, "nextBin= %f, binEnd = %d, bins[%d] = %d\n", nextBin, binEnd, bin_no, binEnd - i ); */ i = binEnd; nextBin += binLen; bin_no++; } bins[bin_no] = lastIdx - i;#endif return 0;}static int ScrollCmd( interp, hist, argc, argv )Tcl_Interp *interp;stateHist *hist;int argc;char *argv[];{ int windowUnits, firstUnit; double fullSpan, visSpan; char cmd[200]; visSpan = hist->right - hist->left; fullSpan = hist->longest - hist->shortest; /* send left/span command to time_lbl */ sprintf( cmd, "%s setview %.10f %.10f\n", hist->time_lbl, hist->left, visSpan ); if (Tcl_Eval( hist->interp, cmd ) != TCL_OK) return TCL_ERROR; windowUnits = 10000 * visSpan / fullSpan; firstUnit = 10000 * (hist->left - hist->shortest) / fullSpan; /* send old-fashioned scroll command to the horizontal scrollbar */ sprintf( cmd, "%s set 10000 %d %d %d", hist->xscrollbar, windowUnits, firstUnit, firstUnit + windowUnits ); if (Tcl_Eval( hist->interp, cmd ) != TCL_OK) return TCL_ERROR; return TCL_OK;}static int XviewCmd( interp, hist, argc, argv )Tcl_Interp *interp;stateHist *hist;int argc;char *argv[];{ int xview; double visSpan, fullSpan, left; if (TCL_OK != ConvertArgs( interp, "hist <token> xview <x>", "3 d", argc, argv, &xview )) { return TCL_ERROR; } /* the scrollbar will scroll everyone right off the screen if you let it */ if (xview<0) xview = 0; visSpan = hist->right - hist->left; fullSpan = hist->longest - hist->shortest; left = xview * fullSpan / 10000 + hist->shortest; if (left < hist->shortest) { left = hist->shortest; } else if (left + visSpan > hist->longest) { left = hist->longest - visSpan; } if (left == hist->left) return TCL_OK; hist->left = left; hist->right = left + visSpan; return Tcl_VarEval( interp, "Hist_Draw ", hist->window, (char*)0 );}static int State_HistClose( hist )stateHist *hist;{ UnlinkVars( hist->interp, hist ); Stats_Close( hist->vis_stats ); free( hist->array_name ); free( hist->idx_prefix ); free( (char*)hist->lens ); free( (char*)hist ); return 0;} /* straight binary search, if item not found we may be one high or one low */static int Bsearch( hist, x, bottom, top )stateHist *hist;double x;int top, bottom;{ int mid; while (top > bottom) { mid = (top + bottom) / 2; if (hist->lens[mid] > x) { /* too high */ top = mid - 1; } else if (hist->lens[mid] < x) { /* too low */ bottom = mid + 1; } else { /* found exact value */ return mid; } } return bottom;}#if 0 /* binary search, return index to an item less than or equal to the given item */static int BsearchLE( hist, x, bottom, top )stateHist *hist;double x;int bottom, top;{ int i; i = Bsearch( hist, x, bottom, top ); if (i && hist->lens[i] > x) { /* if the item found is greater than what we want, decrement */ i--; } else { /* if the item found is equal to what we want, skip over any preceding equal ones */ while (i>0 && hist->lens[i-1] == x) i--; } return i;}#endif /* binary search, return index to an item less than or equal to */static int BsearchGE( hist, x, bottom, top )stateHist *hist;double x;int bottom, top;{ int i; i = Bsearch( hist, x, bottom, top ); if ((i< hist->n-1) && hist->lens[i] < x) { /* if the item found is less than what we want, increment */ i++; } else { /* if the item found is equal to what we want, skip over any succeeding equal ones */ while (i<top-1 && hist->lens[i+1] == x) i++; } return i;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -