Навигация:
<< >> Оглавление Указатель
Текст С++

Полный исходный текст на языке C++ для библиотеки (DLL) с моделями блоков, иллюстрирующих сохранение и загрузку состояния части схемы. Библиотека содержит две модели:

  // Сохранение и загрузка состояния блоков
  #include <windows.h>
  #include <stdio.h>
  #include <math.h>
  #include <RdsDef.h>
  // Подготовка описаний сервисных функций
  
  #include <RdsFunc.h>

  //==========  ==========
  int WINAPI ( /*hinst*/,
                           unsigned long reason,
                           void* /*lpReserved*/)
  { if(reason==DLL_PROCESS_ATTACH) // Загрузка DLL
      { // Получение доступа к функциям RDS
        if(!GetInterfaceFunctions())
           // Сообщение: старая версия RDS
      }
    return 1;
  }
  //========= Конец главной функции =========

  //=========================================
  // Запись и загрузка состояния
  //=========================================
  extern "C" __declspec(dllexport)
      int  SaveLoadState(int CallMode,
                           BlockData,
                           ExtParam)
  {  mouse;
    // Указатель на личную обрасть данных блока (int)
    int *pSaveId=(int*)(BlockData->BlockData);

    switch(CallMode)
      { // Инициализация
        case :
          // Создание личной области данных (одно число int)
          BlockData->BlockData=pSaveId=new int;
          // Исходное значение идентификатора: -1 (т.е. нет)
          *pSaveId=-1;
          break;

        // Очистка
        case :
          // Удаление сохраненного состояния (если есть)
          rdsDeleteSystemState(*pSaveId);
          // Уничтожение личной области
          delete pSaveId;
          break;

        // Нажатие кнопки мыши
        case :
          mouse=()ExtParam;
          if(mouse->Button==) // Левая кнопка
            {  descr;
              descr.servSize=sizeof(descr);
               save=FALSE,load=FALSE;
              // Есть ли у блока картинка?
              (BlockData->Block,&descr);
              if(descr.Flags & )
                { // Картинка есть – смотрим идентификатор элемента
                  // под курсором
                  int pic_id=(mouse);
                  if(pic_id>0)
                    save=TRUE;
                  else if(pic_id<0)
                    load=TRUE;
                }
              else if(mouse->y<mouse->Top+mouse->Height/2)
                save=TRUE; // Картинки нет, верх блока
              else
                load=TRUE; // Картинки нет, низ блока
              if(save) // Сохраняем состояние
                *pSaveId=(BlockData->Parent,
                             *pSaveId,TRUE,NULL);
              if(load) // Загружаем состояние
                { (*pSaveId,NULL);
                  // Необходимо обновить окно подсистемы
                  (BlockData->Parent,TRUE);
                }
            }
          break;
      }
    return ;
  }
  //=========================================

  //==============================================================================
  // В график внесены изменения для поддержки сохранения и загрузки состояния
  //==============================================================================

  //=========================================
  // Простой график – личная область данных
  //=========================================
  class TSimplePlotData
  { private:
      // Запомненные координаты поля графика
      int Gr_x1,Gr_x2,Gr_y1,Gr_y2;
      // Масштаб окна на момент последнего рисования
      double OldZoom;

      // Индекс последнего нарисованного отсчета
      int LastDrawnIndex;

      // Настроечные параметры графика (цвета, шаг и т.п.)
      double TimeStep;          // Шаг записи отсчетов
       Font;  // Шрифт чисел на осях
       BorderColor;     // Цвет рамки вокруг блока
       FillColor;       // Цвет фона блока
       PlotBorderColor; // Цвет рамки поля графика
       PlotFillColor;   // Цвет фона поля графика
       LineColor;       // Цвет лини графика
      int LineWidth;            // Толщина линии графика

      // Ось X
      double Xmin,Xmax;  // Диапазон
      double XGridStep;  // Шаг чисел на осях
      int XNumDecimal;   // Дробная часть чисел на осях

      // Ось Y
      double Ymin,Ymax;  // Диапазон
      double YGridStep;  // Шаг чисел на осях
      int YNumDecimal;   // Дробная часть чисел на осях

      // Массивы для хранения отсчетов графика
      double *Times;     // Массив отсчетов времени
      double *Values;    // Массив значений
      int Count;         // Размер массивов
      int NextIndex;     // Индекс для записи следующего значения
      double NextTime;   // Время записи следующего значения

       Time; // Связь с динамической переменной
                            // времени ("DynTime")
    public:
      // Функция сброса запомненного масштаба последнего рисования
      void ResetCoords(void){OldZoom=-1.0;};

      // Функция отведения массивов отсчетов
      void AllocateArrays(void);
      // Функция освобождения массивов отсчетов
      void ClearArrays(void);
      // Добавление очередной точки в массив отсчетов графика
      void AddPoint(double v);

      int Setup(void);           // Функция настройки параметров
      void SaveText(void);       // Функция сохранения параметров
      void LoadText(char *text); // Функция загрузки параметров
      void Draw( DrawData);     // Функция рисования
      void DrawFast( DrawData); // Функция быстрого рисования
      // Рисование иконки при отсутствии доступа к DynTime
      void DrawAdditional( DrawData);
      // Поиск индекса отсчета, соответствующего времени t
      int FindTimeIndex(double t);
      // Вывод всплывающей полсказки
      void PopupHint( hintdata);

void SaveState(void); // Функция записи состояния void LoadState(void); // Функция загрузки состояния
TSimplePlotData(void); // Конструктор класса ~TSimplePlotData(); // Деструктор класса }; //========================================= // Модель блока extern "C" __declspec(dllexport) int SimplePlot( int CallMode, BlockData, ExtParam) { // #define pStart ((char *)(BlockData->VarTreeData)) #define Start (*((char *)(pStart))) #define Ready (*((char *)(pStart+RDS_VSZ_S))) #define x (*((double *)(pStart+2*RDS_VSZ_S))) // Указатель на личную область, приведенный к правильному типу TSimplePlotData *data=(TSimplePlotData*)(BlockData->BlockData); switch(CallMode) { // Инициализация блока case : BlockData->BlockData=new TSimplePlotData(); break; // Очистка данных блока case : delete data; break; // Проверка типов статических переменных case : if(strcmp((char*)ExtParam,"{SSD}")==0) return ; return ; // Функция настройки параметров case : data->ResetCoords(); // Сброс запомненных значений return data->Setup(); // Загрузка параметров в текстовом формате case : data->LoadText((char*)ExtParam); data->ResetCoords(); // Сброс запомненных значений break; // Созранение параметров в текстовом формате case : data->SaveText(); break; // Изменение размеров блока case : data->ResetCoords(); // Сброс запомненных значений break; // Рисование внешнего вида блока case : //data->Draw(()ExtParam); data->DrawFast(()ExtParam); break; // Дополнительное рисование case : data->DrawAdditional(()ExtParam); break; // Запуск расчета case : if((()ExtParam)->FirstStart) data->AllocateArrays(); // Первый запуск break; // Сброс расчета case : data->ClearArrays(); break; // Реакция на изменение динамической переменной case : data->AddPoint(x); break; // Всплывающая подсказка case : data->PopupHint(()ExtParam); break;
// Запись состояния блока case : data->SaveState(); break;
// Загрузка состояния блока case : data->LoadState(); break;
} return ; // Отмена макроопределений для переменных #undef x #undef Ready #undef Start #undef pStart } //========================================= // Конструктор класса личной области данных графика TSimplePlotData::TSimplePlotData(void) { // Инициализация OldZoom: значение -1 приведет к принудительному // вычислению Gr_x1,Gr_x2,Gr_y1 и Gr_y2 в ближайшем вызове // функции Draw OldZoom=-1.0; // Инициализация LastDrawnIndex LastDrawnIndex=-1; // Присвоение начальных значений параметрам TimeStep=0.1; // Шаг записи BorderColor=0; // Цвет рамки вокруг блока FillColor=0xffffff; // Цвет фона блока PlotBorderColor=0; // Цвет рамки окна графика и сетки PlotFillColor=0xffffff; // Цвет окна графика LineColor=0; // Цвет линии графика LineWidth=1; // Толщина линии графика // Параметры шрифта Font.servSize=sizeof(Font); strcpy(Font.Name,"Arial"); Font.SizePriority=FALSE; Font.Height=15; Font.Color=0; Font.Bold=Font.Italic=Font.Underline=Font.StrikeOut=FALSE; Font.CharSet=; // Диапазоны осей, шаг сетки, число десятичных знаков // в числах на осях Xmin=0.0; Xmax=10.0; XGridStep=5.0; XNumDecimal=0; Ymin=-1.0; Ymax=1.0; YGridStep=0.5; YNumDecimal=1; // Обнуление указателей на массивы и их размера // (массивы еще не отведены) Times=Values=NULL; Count=NextIndex=0; NextTime=Xmin; // Подписка на динамическую переменную времени Time=( ,// В родительской подсистеме "DynTime", // Имя переменной "D", // Тип переменной (double) TRUE); // Искать по иерархии } //========================================= // Деструктор класса TSimplePlotData::~TSimplePlotData() { (Time); // Прекратить подписку ClearArrays(); // Освободить массивы } //========================================= // Рисование внешнего вида блока void TSimplePlotData::Draw( DrawData) { // Вспомогательные переменные // int Gr_x1,Gr_x2,Gr_y1,Gr_y2; - эти переменные стали // полями класса int x1,y1,x2,y2,textheight,w1,w2; char buf[80]; // Рамка графика (0,,1,BorderColor,); (0,,FillColor); (DrawData->Left,DrawData->Top, DrawData->Left+DrawData->Width, DrawData->Top+DrawData->Height); // Необходимо вычислить координаты поля графика относительно // верхнего левого угла блока // Установка параметров шрифта с учетом масштаба (&Font,DrawData->DoubleZoom); ("0",NULL,&textheight); if(DrawData->DoubleZoom!=OldZoom) // Масштаб изменен { // Зазор сверху – половина высоты цифры + 1 точка Gr_y1=textheight/2+1; // Зазор снизу – полная высота цифры + 1 точка Gr_y2=DrawData->Height-textheight-1; // Зазор слева – ширина самого длинного числа вертикальной // оси или половина ширины Xmin sprintf(buf," %.*lf ",YNumDecimal,Ymin); (buf,&w1,NULL); // Ширина Ymin sprintf(buf," %.*lf ",YNumDecimal,Ymax); (buf,&w2,NULL); // Ширина Ymax if(w2>w1) w1=w2; sprintf(buf," %.*lf ",XNumDecimal,Xmin); (buf,&w2,NULL); // Ширина Xmin w2/=2; if(w2>w1) w1=w2; Gr_x1=w1; // Зазор справа – половина ширины Xmax sprintf(buf," %.*lf ",XNumDecimal,Xmax); (buf,&w2,NULL); // Ширина Xmax w2/=2; Gr_x2=DrawData->Width-w2; // Запоминание нового масштаба OldZoom=DrawData->DoubleZoom; } // if(DrawData->DoubleZoom!=OldZoom) // Абсолютные (на рабочем поле) координаты поля графика x1=DrawData->Left+Gr_x1; x2=DrawData->Left+Gr_x2; y1=DrawData->Top+Gr_y1; y2=DrawData->Top+Gr_y2; if(x1>=x2 || y1>=y2) // Негде рисовать return; // Прямоугольник поля графика (0,,1,PlotBorderColor,); (0,,PlotFillColor); (x1,y1,x2,y2); // Установка пунктирного стиля линии (0,,1,PlotBorderColor,); (0,,0); // Без заливки // Горизонтальная ось с сеткой for(double x=Xmin;x<=Xmax+XGridStep*0.5;x+=XGridStep) { // ix - координата линии на рабочем поле int ix=x1+(x-Xmin)*(x2-x1)/(Xmax-Xmin); if(ix>x1 && ix<x2) // Чертим вертикальную линию { (ix,y1); (ix,y2); } // Вывод числа на оси под полем sprintf(buf,"%.*lf",XNumDecimal,x); (buf,&w1,NULL); (ix-w1/2,y2,buf); } // Вертикальная ось с сеткой for(double y=Ymin;y<=Ymax+YGridStep*0.5;y+=YGridStep) { // iy - координата линии на рабочем поле int iy=y2-(y-Ymin)*(y2-y1)/(Ymax-Ymin); if(iy>y1 && iy<y2) // Чертим горизонтальную линию { (x1,iy); (x2,iy); } // Вывод числа на оси слева от поля sprintf(buf,"%.*lf ",YNumDecimal,y); (buf,&w1,&textheight); (x1-w1-2,iy-textheight/2,buf); } // Если массивы не пустые – рисовать график if(Count) { r; // Установить область отсечения рисования по полю графика r.left=x1+1; r.top=y1+1; r.right=x2-1; r.bottom=y2-1; (&r); // Установить сплошной стиль линии, заданный для // графика цвет и толщину линии с учетом масштаба (0,, LineWidth*DrawData->DoubleZoom, LineColor,); // Строим ломанную линию по отсчетам из массивов for(int i=0;i<NextIndex;i++) { // Преобразуем вещественные отсчеты в целочисленные // координаты на рабочем поле int ix=x1+(Times[i]-Xmin)*(x2-x1)/(Xmax-Xmin), iy=y2-(Values[i]-Ymin)*(y2-y1)/(Ymax-Ymin); if(i) // Не первая точка – строим линию от предыдущей (ix,iy); else // Первая точка графика – делаем ее текущей (ix,iy); } // Запоминаем последний нарисованный отсчет LastDrawnIndex=NextIndex-1; // Отмена отсечения (NULL); } } //========================================= // Рисование изменений void TSimplePlotData::DrawFast( DrawData) { int x1,y1,x2,y2; // Если RDS требует полного рисования, или полное рисование // еще не проводилось, вызывается старая функция Draw if(DrawData->FullDraw || DrawData->DoubleZoom!=OldZoom) { Draw(DrawData); return; } // Вычисление абсолютных координат поля графика x1=DrawData->Left+Gr_x1; x2=DrawData->Left+Gr_x2; y1=DrawData->Top+Gr_y1; y2=DrawData->Top+Gr_y2; if(x1>=x2 || y1>=y2) // Негде рисовать return; // Если массивы не пустые – рисовать график, начиная // с последней уже нарисованной точки if(Count) { r; // Установить область отсечения рисования по полю графика r.left=x1+1; r.top=y1+1; r.right=x2-1; r.bottom=y2-1; rdsXGSetClipRect(&r); // Установить сплошной стиль линии, заданный для // графика цвет и толщину линии с учетом масштаба (0,, LineWidth*DrawData->DoubleZoom, LineColor,); // Проверка допустимости LastDrawnIndex – на всякий случай if(LastDrawnIndex<0) LastDrawnIndex=0; // Строим ломанную линию по отсчетам из массивов, // начиная с LastDrawIndex for(int i=LastDrawnIndex;i<NextIndex;i++) { int ix=x1+(Times[i]-Xmin)*(x2-x1)/(Xmax-Xmin), iy=y2-(Values[i]-Ymin)*(y2-y1)/(Ymax-Ymin); if(i!=LastDrawnIndex) (ix,iy); else (ix,iy); } // Запоминаем последний нарисованный отсчет LastDrawnIndex=NextIndex-1; // Отмена отсечения (NULL); } } //========================================= // Дополнительное рисование void TSimplePlotData::DrawAdditional( DrawData) { // Проверка доступа к переменной времени if(Time==NULL || Time->Data==NULL) // Доступа нет { int w,h; // Константа, указывающая на стандартную иконку RDS icon=; // Определяем размер иконки и выводим ее в центре блока if((icon,&w,&h)) (DrawData->Left+(DrawData->Width-w)/2, DrawData->Top+(DrawData->Height-h)/2, icon); } } //========================================= // Отведение памяти под массивы void TSimplePlotData::AllocateArrays(void) { // Сначала нужно очистить массивы, если они были отведены ранее ClearArrays(); // При нулевом или отрицательном шаге записи отсчетов // работа блока невозможна if(TimeStep<=0.0) return; // Вычисление требуемого числа отсчетов по диапазону оси // времени и шагу записи Count=(Xmax-Xmin)/TimeStep+1; // Число отсчетов должно быть положительным if(Count<=0) {Count=0; return; } // Отведение памяти – по Count чисел double Times=new double[Count]; Values=new double[Count]; // Первый свободный индкс массива - 0 NextIndex=0; // Момент записи отсчета – начало диапазона оси времени NextTime=Xmin; } //========================================= // Освобождение массивов void TSimplePlotData::ClearArrays(void) { if(Count) // Массивы были отведены { delete[] Times; delete[] Values; } // Обнуление указателей и Count Times=Values=NULL; Count=NextIndex=0; } //========================================= // Добавление отсчета в массив void TSimplePlotData::AddPoint(double v) { double t; if(NextIndex>=Count) // Весь массив заполнен return; if(Time==NULL || Time->Data==NULL) // Нет доступа к “DynTime" return; // Получение значения времени из “DynTime" t=*((double*)Time->Data); if(t<NextTime) // Еще не пришло время писать отсчет return; // Достигнуто время записи Values[NextIndex]=v; Times[NextIndex]=t; NextIndex++; // Следующий отсчет – в следующий индекс NextTime+=TimeStep; // Время записи следующего отсчета } //========================================= // Сохранение параметров в текстовом виде void TSimplePlotData::SaveText(void) { ini; char *str; // Создание объекта для работы с текстом ini=(TRUE); // Создание в тексте секции "[General]" (ini,,0,"General"); // Запись в секцию различных параметров (ini,"TimeStep",TimeStep); (ini,"Xmin",Xmin); (ini,"Xmax",Xmax); (ini,"XGridStep",XGridStep); (ini,"XNumDecimal",XNumDecimal); (ini,"Ymin",Ymin); (ini,"Ymax",Ymax); (ini,"YGridStep",YGridStep); (ini,"YNumDecimal",YNumDecimal); // Создание в тексте секции "[Visuals]" (ini,,0,"Visuals"); // Запись в секцию различных параметров (ini,"BorderColor",(int)BorderColor); (ini,"FillColor",(int)FillColor); (ini,"PlotBorderColor",(int)PlotBorderColor); (ini,"PlotFillColor",(int)PlotFillColor); (ini,"LineColor",(int)LineColor); (ini,"LineWidth",LineWidth); // Преобразование описания шрифта в строку для сохранения str=(&Font,NULL); // Запись строки с описанием шрифта (ini,"Font",str); (str); // Освобождение памяти, занятой строкой // Запись сформированного текста в файл схемы или буфер обмена (ini,); // Уничтожение вспомогательного объекта (ini); } //========================================= // Загрузка параметров в текстовом виде из строки text void TSimplePlotData::LoadText(char *text) { ini; char *str; // Создание объекта для работы с текстом ini=(TRUE); // Загрузка текста в объект (ini,,0,text); // Если в тексте есть секция "General", загрузить из нее данные if((ini,"General")) { TimeStep=(ini,"TimeStep",TimeStep); Xmin=(ini,"Xmin",Xmin); Xmax=(ini,"Xmax",Xmax); XGridStep=(ini,"XGridStep",XGridStep); XNumDecimal=(ini,"XNumDecimal",XNumDecimal); Ymin=(ini,"Ymin",Ymin); Ymax=(ini,"Ymax",Ymax); YGridStep=(ini,"YGridStep",YGridStep); YNumDecimal=(ini,"YNumDecimal",YNumDecimal); } // Если в тексте есть секция "Visuals", загрузить из нее данные if((ini,"Visuals")) { BorderColor=()(ini,"BorderColor", (int)BorderColor); FillColor=()(ini,"FillColor", (int)FillColor); PlotBorderColor=()(ini, "PlotBorderColor",(int)PlotBorderColor); PlotFillColor=()(ini,"PlotFillColor", (int)PlotFillColor); LineColor=()(ini,"LineColor", (int)LineColor); LineWidth=()(ini,"LineWidth",LineWidth); str=(ini,"Font","",NULL); if(str) (str,NULL,&Font); } // Уничтожение вспомогательного объекта (ini); } //========================================= // Функция настройки параметров блока // // // int TSimplePlotData::Setup(void) { window; BOOL ok; char *str; // Создание окна window=(TRUE,-1,-1,"Простой график"); // Вкладка "Оси" (window,1,"Оси"); (window,1,100, | ,"Шаг записи",50); (window,100,,TimeStep); // Текстовая метка без возможности ввода (window,1,1,,"Ось X:",0); // Диапазон (два поля ввода в одной строке) (window,1,2,,"Диапазон",90); (window,2,,Xmin); (window,2,,Xmax); (window,1,3,,"Шаг сетки",50); (window,3,,XGridStep); // Поле ввода со стрелками увеличения/уменьшения (window,1,4, | , "Дробная часть чисел",50); (window,4,,XNumDecimal); (window,4,,0); (window,4,,5); (window,4,,1); // Текстовая метка без возможности ввода (window,1,5,,"Ось Y:",0); (window,1,6,,"Диапазон",90); (window,6,,Ymin); (window,6,,Ymax); (window,1,7,,"Шаг сетки",50); (window,7,,YGridStep); (window,1,8,, "Дробная часть чисел",50); (window,8,,YNumDecimal); (window,8,,0); (window,8,,5); (window,8,,1); // Вкладка "Внешний вид" (window,2,"Внешний вид"); (window,2,9,, "Цвет рамки блока",50); (window,9,,(int)BorderColor); (window,2,10, | ,"Цвет фона блока",50); (window,10,,(int)FillColor); (window,2,11,, "Цвет рамки графика и сетки",50); (window,11,, (int)PlotBorderColor); (window,2,12,, "Цвет фона графика",50); (window,12,,(int)PlotFillColor); (window,2,13,, "Цвет линии графика",50); (window,13,,(int)LineColor); (window,2,14, | , "Толщина линии графика",50); (window,14,,LineWidth); (window,14,,0); (window,14,,5); (window,14,,1); // Кнопка открытия диалога выбора шрифта (window,2,15,, "Шрифт чисел",0); // Преобразование шрифта в строку и занесение в поле ввода str=(&Font,NULL); (window,15,,str); (str); // Открытие окна ok=(window,NULL); if(ok) { // Нажата кнопка OK - запись параметров обратно в блок Xmin=(window,2,); Xmax=(window,2,); XGridStep=(window,3,); XNumDecimal=(window,4,); TimeStep=(window,100,); Ymin=(window,6,); Ymax=(window,6,); YGridStep=(window,7,); YNumDecimal=(window,8,); BorderColor=()(window,9,); FillColor=()(window,10,); PlotBorderColor=()(window,11,); PlotFillColor=()(window,12,); LineColor=()(window,13,); LineWidth=(window,14,); // Получение параметров шрифта из строки str=(window,15,); (str,NULL,&Font); } // Уничтожение окна (window); // Возвращаемое значение return ok?:; } //========================================= // Всплывающая подсказка // // // void TSimplePlotData::PopupHint( hintdata) { int x1,x2,y1,y2,index; double t; char *text,*str_t,*str_v; // Проверка доступа к переменной времени if(Time==NULL || Time->Data==NULL) { ("ОШИБКА: в схеме нет переменной DynTime"); return; } // Определение абсолютных координат поля графика x1=hintdata->Left+Gr_x1; x2=hintdata->Left+Gr_x2; y1=hintdata->Top+Gr_y1; y2=hintdata->Top+Gr_y2; // Если курсор мыши не попадает в поле графика, // подсказку выводить не нужно if(hintdata->x<x1 || hintdata->x>x2 || hintdata->y<y1 || hintdata->y>y2) return; // Преобразование экранной горизонтальной координаты // в значение времени согласно масштабу графика t=(hintdata->x-x1)*(Xmax-Xmin)/(x2-x1)+Xmin; // Поиск отсчета, соответствующего этому моменту времени index=FindTimeIndex(t); if(index<0) return; // Ошибка – отчет не найден // Преобразование времени и значения отсчета в строки str_t=(Times[index],-1,NULL); str_v=(Values[index],-1,NULL); // Формирование текста подсказки text=("Время: ",str_t,FALSE); (&text,"\nЗначение: ",FALSE); (&text,str_v,FALSE); // Установка текста подсказки (text); // Освобождение динамических строк (text); (str_t); (str_v); // Изменение параметров подсказки таким образом, чтобы при // смещении курсора на одну точку она вывелась снова hintdata->HZLeft=hintdata->x; hintdata->HZTop=hintdata->y; hintdata->HZWidth=hintdata->HZHeight=1; // Задержка гашения подсказки – одна минута hintdata->HideTimeout=60000; } //========================================= /* // Поиск отсчета, соответствующего времени t // (линейный поиск) int TSimplePlotData::FindTimeIndex(double t) { if(Count==0) // Массивы пусты return -1; if(t<=Times[0]) // t раньше начала массива return 0; // Ближайший индекс - 0 // Поиск первого индекса, большего t for(int i=1;i<NextIndex;i++) if(Times[i]>t) // t между i-1 и i { double d1=fabs(t-Times[i-1]), d2=fabs(t-Times[i]); return (d1<d2)?(i-1):i; // Возвращаем ближайший } // Ничего не нашли – значит, t>Times[NextIndex-1] return NextIndex-1; } //========================================= */ // Поиск отсчета, соответствующего времени t // (метод деления пополам) int TSimplePlotData::FindTimeIndex(double t) { int L,R; double dl,dr; if(Count==0 || NextIndex==0) // Нет данных в массивах return -1; if(NextIndex==1) // В массиве единственный отсчет return 0; // В массиве по крайней мере два значения – проверяем границы if(t<=Times[0])// t меньше первого отсчета return 0; if(t>=Times[NextIndex-1]) // t больше последнего отсчета return NextIndex-1; // t - внутри диапазона массива L=0; R=NextIndex-1; while(L<R-1) { int m=(L+R)/2; if(Times[m]<t) L=m; else R=m; } // t лежит между L и R dl=fabs(t-Times[L]), dr=fabs(t-Times[R]); return (dl<dr)?L:R; // Возвращаем ближайший } //=========================================
// Запись состояния блока void TSimplePlotData::SaveState(void) { // Макрос для записи одной переменной #define WRITEBLOCKDATAVAR(v) (&v,sizeof(v)) WRITEBLOCKDATAVAR(TimeStep); WRITEBLOCKDATAVAR(Xmin); WRITEBLOCKDATAVAR(Xmax); WRITEBLOCKDATAVAR(XGridStep); // Запись массивов отсчетов (Times,Count*sizeof(double)); (Values,Count*sizeof(double)); WRITEBLOCKDATAVAR(NextIndex); WRITEBLOCKDATAVAR(NextTime); // Отмена макроса #undef WRITEBLOCKDATAVAR } //=========================================
// Загрузка состояния блока void TSimplePlotData::LoadState(void) { // Макрос для загрузки одной переменной #define READBLOCKDATAVAR(v) (&v,sizeof(v)) READBLOCKDATAVAR(TimeStep); READBLOCKDATAVAR(Xmin); READBLOCKDATAVAR(Xmax); READBLOCKDATAVAR(XGridStep); // Отведение массивов перед загрузкой AllocateArrays(); (Times,Count*sizeof(double)); (Values,Count*sizeof(double)); READBLOCKDATAVAR(NextIndex); READBLOCKDATAVAR(NextTime); // Отмена макроса #undef READBLOCKDATAVAR // Сброс параметров оптимизации рисования OldZoom=-1.0; LastDrawnIndex=-1; } //=========================================


<< >> Оглавление Указатель