⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trend.cc

📁 Develop Zigbee network real-time Os
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* * trend: display live data on a trend graph * Copyright(c) 2003-2005 by wave++ "Yuri D'Elia" <wavexx@users.sf.net> * Distributed under GNU LGPL WITHOUT ANY WARRANTY. *//* * Headers */// defaults#include "defaults.hh"#include "color.hh"#include "timer.hh"#include "rr.hh"// system headers#include <stdexcept>#include <vector>using std::vector;#include <iostream>using std::cout;using std::cerr;using std::cin;#include <string>using std::string;#include <utility>using std::pair;#include <limits>using std::numeric_limits;// c system headers#include <cstdlib>using std::strtod;using std::strtoul;#include <cstring>using std::memcpy;using std::strlen;using std::strpbrk;using std::strchr;#include <math.h>#include <stdio.h>#include <ctype.h>#include <sys/stat.h>#include <unistd.h>#include <errno.h>#include <pthread.h>#ifdef __sgi#include <mutex.h>#endif// OpenGL/GLU#include "gl.hh"#ifndef NAN#define NAN numeric_limits<double>::quiet_NaN()#endif/* * Data structures */struct Value{  Value()  {}  Value(double value, size_t count)  : value(value), count(count)  {}  double value;  size_t count;};struct Intr{  // nearest value  Value near;    // intersection  double value;  double dist;};booloperator<(const Intr& l, const Intr& r){  return (l.dist < r.dist);}struct Grid{  double res;  unsigned long mayor;};struct GrSpec{  Grid x;  Grid y;};/* * Graph/Program state */namespace{  // Basic data  const char* fileName;  pthread_mutex_t mutex;  volatile unsigned long damaged = 0;  Trend::input_t input = Trend::input;  Trend::format_t format = Trend::format;  // Data and fixed parameters  rr<Value>* rrData;  Value* rrBuf;  Value* rrEnd;  double loLimit;  double hiLimit;  double grZero = 0.;  // Visual/Fixed settings  size_t history;  size_t divisions;  size_t offset;  const char* title = NULL;  GLfloat backCol[3];  GLfloat textCol[3];  GLfloat gridCol[3];  GLfloat lineCol[3];  GLfloat markCol[3];  GLfloat intrCol[3];  // Visual/Changeable settings  int width;  int height;  int lc;  bool autoLimit;  bool dimmed = Trend::dimmed;  bool fifo = Trend::fifo;  bool smooth = Trend::smooth;  bool scroll = Trend::scroll;  bool values = Trend::values;  bool marker = Trend::marker;  bool grid = Trend::grid;  GrSpec grSpec;  bool paused = false;  // Indicator status  bool intr = false;  bool intrFg;  double intrX;  double intrY;  // Distribution graph  bool distrib = Trend::distrib;  vector<double> distribData;  // Latency  bool latency = Trend::latency;  ATimer atLat(Trend::latAvg);}/* * I/O and data manipulation */// fill the round robin consistently with a single valuevoidfillRr(double value, size_t start = 0){  Value buf;  buf.count = start;  buf.value = value;  for(size_t i = 0; i != history; ++i)  {    rrData->push_back(buf);    if(!(++buf.count % divisions))      buf.count = 0;  }}// skip whitespacevoidskipSpc(FILE* fd){  int c;  do { c = getc_unlocked(fd); }  while(isspace(c) && c != EOF);  ungetc(c, fd);}// skip a space-separated stringvoidskipStr(FILE* fd){  int c;  do { c = getc_unlocked(fd); }  while(!isspace(c) && c != EOF);  ungetc(c, fd);}// read a space-separated stringchar*readStr(FILE* fd, char* buf, size_t len){  char* p(buf);  int c;  while(len--)  {    c = getc_unlocked(fd);    if(c == EOF || isspace(c))    {      ungetc(c, fd);      return p;    }    *p++ = c;  }  // overflow  return NULL;}// read a number from an ascii streamdoublereadANum(FILE* fd){  // read a number  double num;  for(;;)  {    // read    skipSpc(fd);    char buf[Trend::maxNumLen];    char* end = readStr(fd, buf, sizeof(buf) - 1);    if(feof(fd))      return NAN;    if(!end)    {      // long string, skip it.      skipStr(fd);      continue;    }    *end = 0;      // convert the number    num = strtod(buf, &end);    if(end != buf)      break;  }    return num;}// read a number from a binary streamtemplate <class T> doublereadNum(FILE* fd){  T buf;  return (fread(&buf, sizeof(buf), 1, fd)?      static_cast<double>(buf): NAN);}// read up to the first number in the stream using the current formatdoublereadFNum(FILE* fd){  double num;  switch(format)  {  case Trend::f_ascii: num = readANum(fd); break;  case Trend::f_float: num = readNum<float>(fd); break;  case Trend::f_double: num = readNum<double>(fd); break;  case Trend::f_short: num = readNum<short>(fd); break;  case Trend::f_int: num = readNum<int>(fd); break;  case Trend::f_long: num = readNum<long>(fd); break;  }  return num;}// producer threadvoid*producer(void* prg){  // iostreams under gcc 3.x are completely unusable for advanced tasks such as  // customizable buffering/locking/etc. They also removed the (really  // standard) ->fd() access for "encapsulation"...  FILE* in;  for(size_t pos = (history % divisions);;)  {    // open the file and disable buffering    in = fopen(fileName, "r");    if(!in) break;    setvbuf(in, NULL, _IONBF, 0);    // check for useless file types    struct stat stBuf;    fstat(fileno(in), &stBuf);    if(S_ISDIR(stBuf.st_mode))      break;    // first value for incremental data    double old, num;    if(input != Trend::absolute)      old = readFNum(in);    // read all data    while(!isnan((num = readFNum(in))))    {      // determine the actual value      switch(input)      {      case Trend::incremental:        {	  double tmp = num;	  num = (num - old);	  old = tmp;        }	break;      case Trend::differential:	old += num;	num = old;	break;      }      // append the value      rrData->push_back(Value(num, pos));#ifdef __sgi      add_then_test((unsigned long*)(&damaged), 1);#else      pthread_mutex_lock(&mutex);      ++damaged;      pthread_mutex_unlock(&mutex);#endif      // wrap pos when possible      if(!(++pos % divisions))	pos = 0;    }    // close the stream and terminate the loop for regular files    fclose(in);    if(S_ISREG(stBuf.st_mode) || S_ISBLK(stBuf.st_mode))      break;  }  // should never get so far  cerr << reinterpret_cast<char*>(prg) << ": producer thread exiting\n";  return NULL;}/* * OpenGL functions */// project model coordinatesvoidproject(double xi, double yi, int& xo, int& yo){  int width(distrib? ::width - Trend::distribWidth: ::width);  int off(distrib? Trend::distribWidth: 0);  xo = (off + static_cast<int>(xi * width / divisions));  yo = static_cast<int>((yi - loLimit) * height / (hiLimit - loLimit));}// unproject video to model coordinatesvoidunproject(int xi, int yi, double& xo, double& yo){  int width = (distrib? ::width - Trend::distribWidth: ::width);  int xr = (distrib? xi - Trend::distribWidth: xi);  xo = (static_cast<double>(divisions) * xr / width);  yo = hiLimit - (static_cast<double>(hiLimit - loLimit) * yi / height);}// OpenGL state initializervoidinit(){  // Smoothing  if(smooth)  {    glEnable(GL_LINE_SMOOTH);    glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);  }  else    glDisable(GL_LINE_SMOOTH);  // Blending should be enabled by default  glEnable(GL_BLEND);  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  // Clear color  glClearColor(backCol[0], backCol[1], backCol[2], 0.0);}// Resize handlervoidreshape(const int w, const int h){  width = w;  height = h;  glViewport(0, 0, w, h);}// write a normal stringvoiddrawString(const int x, const int y, const char* str){  glRasterPos2i(x, y);  for(const char* p = str; *p; ++p)    glutBitmapCharacter(GLUT_BITMAP_8_BY_13, *p);}// write strings in the lower-left cornervoiddrawLEString(const char* str){  drawString(Trend::strSpc, Trend::strSpc + Trend::fontHeight * lc++, str);}// write an on-screen string using video coordinatesvoiddrawOSString(const int x, const int y, const char* str){  using Trend::strSpc;  using Trend::fontHeight;  int len(strlen(str) * 8);  int rx(x + strSpc);  int ry(y + strSpc);  // check x  if((rx + strSpc + len) > width)    rx = width - len - strSpc;  if(rx < 0)    rx = strSpc;  // check y  if((ry + strSpc + fontHeight) > height)    ry = height - fontHeight - strSpc;  if(ry < 0)    ry = strSpc;  drawString(rx, ry, str);}voiddrawGridX(double gridres){  // horizontal lines  double it;  glBegin(GL_LINES);  if(scroll)    for(it = divisions; it > 0; it -= gridres)    {      glVertex2d(it, loLimit);      glVertex2d(it, hiLimit);    }  else    for(it = gridres; it <= divisions; it += gridres)    {      glVertex2d(it, loLimit);      glVertex2d(it, hiLimit);    }  glEnd();}voiddrawGridY(double gridres){  // vertical lines  double it = loLimit - fmod(loLimit - grZero, gridres);  if(it <= loLimit)    it += gridres;  glBegin(GL_LINES);  for(; it < hiLimit; it += gridres)  {    glVertex2d(0, it);    glVertex2d(divisions, it);  }  glEnd();}voiddrawGrid(){  using Trend::maxGridDens;  double r, d;  // x  r = (divisions / grSpec.x.res);  d = (width / maxGridDens);  if(r < (d * grSpec.x.mayor))  {    // minor lines    if(grSpec.x.mayor != 1 && r < d)    {      glColor4f(gridCol[0], gridCol[1], gridCol[2], 0.5);      drawGridX(grSpec.x.res);    }    // mayor lines    if(grSpec.x.mayor)    {      glColor3fv(gridCol);      drawGridX(grSpec.x.res * grSpec.x.mayor);    }  }  // y  r = ((hiLimit - loLimit) / grSpec.y.res);  d = (height / maxGridDens);    if(r < (d * grSpec.y.mayor))  {    // minor lines    if(grSpec.y.mayor != 1 && r < d)    {      glColor4f(gridCol[0], gridCol[1], gridCol[2], 0.5);      drawGridY(grSpec.y.res);    }    // mayor lines    if(grSpec.y.mayor)    {      glColor3fv(gridCol);      drawGridY(grSpec.y.res * grSpec.y.mayor);    }  }}voiddrawMarker(const double x){  glColor3fv(markCol);  glBegin(GL_LINES);  glVertex2d(x, loLimit);  glVertex2d(x, hiLimit);  glEnd();}voiddrawCircle(const int x, const int y){  using Trend::intrRad;  // ok, it's not really a circle.  glBegin(GL_LINE_LOOP);  glVertex2i(x - intrRad, y);  glVertex2i(x, y + intrRad);  glVertex2i(x + intrRad, y);  glVertex2i(x, y - intrRad);  glEnd();}// get drawing position based on current settingssize_tgetPosition(size_t pos, const Value& value){  return ((scroll? pos: value.count) % divisions);}size_tdrawLine(){  const Value* it = rrBuf;  const Value* end = rrEnd;  const size_t mark(history + offset - divisions);  size_t pos;  glBegin(GL_LINE_STRIP);  for(size_t i = offset; it != end; ++i, ++it)  {    // shade the color    double alpha(dimmed?	(i > mark? 1.: .5):	(static_cast<float>(i - offset) / history));	    glColor4f(lineCol[0], lineCol[1], lineCol[2], alpha);    pos = getPosition(i, *it);    if(!pos)    {      // Cursor at the end      glVertex2d(divisions, it->value);      glEnd();      glBegin(GL_LINE_STRIP);      glVertex2d(0, it->value);    }    else      glVertex2d(pos, it->value);  }  glEnd();  return pos;}voiddrawDistrib(){  // reallocate only if necessary. we must avoid to reallocate in order to  // not fragment memory (resize() on gcc 3 isn't very friendly)  if(distribData.size() != static_cast<size_t>(height))    distribData.resize(height);  // calculate distribution  const Value* it = rrBuf;  const Value* end = rrEnd - 1;  distribData.assign(distribData.size(), 0.);  double max = 0;  for(; it != end; ++it)  {    const Value* a = it;    const Value* b = (it + 1);    // projection    double mul = (static_cast<double>(height) / (hiLimit - loLimit));    int begin = static_cast<int>(mul * (a->value - loLimit));    int end = static_cast<int>(mul * (b->value - loLimit));    if(begin > end) std::swap(begin, end);    // fixation    if(end < 0 || begin > height) continue;    if(begin < 0) begin = 0;    if(end > height) end = height;    // integration    for(int y = begin; y != end; ++y)    {      if(++distribData[y] > max)	max = distribData[y];    }  }  if(max != 0.)    max = 1. / max;  // draw the results (optimize for continue zones)  glPushMatrix();  glLoadIdentity();  gluOrtho2D(0, width, 0, height);  using Trend::distribWidth;  double oldColor = distribData[0] * max;  glColor3d(oldColor, oldColor, oldColor);  glBegin(GL_QUADS);  glVertex2i(0, 0);  glVertex2i(distribWidth, 0);  for(int y = 1; y != (height - 1); ++y)  {    double color = distribData[y] * max;    if(color != oldColor)    {      glVertex2i(distribWidth, y);      glVertex2i(0, y);      oldColor = color;      glColor3d(color, color, color);      glVertex2i(0, y);      glVertex2i(distribWidth, y);    }  }  glVertex2i(distribWidth, height);  glVertex2i(0, height);  glEnd();  glPopMatrix();}voiddrawIntr(){  // initial color and current position  glColor3fv(intrCol);  glBegin(GL_LINES);  glVertex2d(intrX, loLimit);  glVertex2d(intrX, hiLimit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -