C++Builder
  Начало   Форум   Помощь Войти Регистрация  
Страниц: [1]   Вниз
  Печать  
Автор Тема: Компонент для создания графика в виде столбиков  (Прочитано 4036 раз)
brdm
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 59


Компонент для создания графика в виде столбиков
« : 21 Июль 2014, 20:44:52 »

Имеются выходные данные 32 точечного БПФ в виде long чисел. Необходимо построить график в виде рядом стоящих 32_ух столбиков (забора) высота которых будет соотноситься с выходными данными БПФ.
Подскажите пожалуйста как это лучше сделать. На базе какого компонента C++Builder6? 
Записан
S0mbre
Глобальный модератор


Сказали спасибо: +1113/-22
Offline

Сообщений: 2132

S0mbre


Re: Компонент для создания графика в виде столбиков
« Ответ #1 : 21 Июль 2014, 22:05:03 »

Из готовых первый приходит в голову TeeChart. А если локально для этой задачи - можно самому руками нарисовать в TPaintBox.
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Компонент для создания графика в виде столбиков
« Ответ #2 : 21 Июль 2014, 22:08:30 »

TChart.
Series к нему типа  Area. Столбики друг от друга отделяешь нулевыми значениями. Каждый столбик можешь красить в любой цвет.

Вот пример на Делфи (билдера в наличии нет)
Код
procedure TForm2.FormShow(Sender: TObject);
var
 i:  Integer;
 cl: TColor;
begin
 for i := 0 to 31 do  begin
   cl := RGB(i*6, i*6, i*6);
   Series1.AddXY(i, i/32, '', cl); // выводимое значение в начале столбика
   Series1.AddXY(i+0.5, i/32, '', cl); // выводимое значение в конце столбика
   Series1.AddXY(i+0.5, 0, '', cl); // ноль в начале промежутка
   Series1.AddXY(i+1, 0, '', cl); // ноль в конце промежутка (начале нового столбика)
 end;
end;
 
« Последнее редактирование: 21 Июль 2014, 22:17:05 от POV » Записан
brdm
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 59


Re: Компонент для создания графика в виде столбиков
« Ответ #3 : 22 Июль 2014, 09:25:04 »

Спасибо. Получилось. Теперь остался вопрос как передать массив типа ResMass[32] из основной формы типа Form1 в Form2 на которой расположен график?
Пробую применить простейший способ.
Код:
Unit1.cpp
....  
long ResMass[32];

Unit2.cpp
....  
extern long ResMass[32];
Проблема в том, что ResMass[32] вычисляется в функции котораая включена в поток (Unit1.cpp)
Код:
// поток pcap
DWORD WINAPI Input_thread( LPVOID lpParam )
{
  pcap_loop(adhandle, 0, packet_handler, NULL);
  return 0;
}
//---------------------------------------------------------------------------
// приемник пакетов

double *x,*y;
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{

тут вычисляется ResMass
И во второй форме данные не видны.  Как сделать правильно, чтобы массив вычисленный в функции потока передать в Form2 (Unin2.cpp)?
« Последнее редактирование: 22 Июль 2014, 10:41:35 от brdm » Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Компонент для создания графика в виде столбиков
« Ответ #4 : 22 Июль 2014, 10:54:35 »

нафиг extern. сделай метод в который передаешь указатель на свой локальный массив.
Записан
brdm
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 59


Re: Компонент для создания графика в виде столбиков
« Ответ #5 : 22 Июль 2014, 11:06:41 »

Массив глобальный. Хотя это наверное и неважно.
А как это выглядит в коде? В смысле как создается метод в который передается указатель на массив ResMass[32]
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Компонент для создания графика в виде столбиков
« Ответ #6 : 22 Июль 2014, 11:10:03 »

Код
long ResMass[32];
 
...
 
SednArray(ResMass);



а вот что в другом модуле:



Код
SendArray(long array[])
{
...
}
Записан
brdm
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 59


Re: Компонент для создания графика в виде столбиков
« Ответ #7 : 22 Июль 2014, 11:28:42 »

Не врубился.
1. Создана глобальная переменная long ResMass[32] в Unit1.cpp

В функции которая включена в поток (прием Ethernet пакета с пом. библиотеки WinPcap) производится вычисление и заполнение данных ResMass[32] которые нужно передать в Unit2.cpp
Не врубился, что такое SednArray(ResMass); Функция? Как она сформирована? 





Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Компонент для создания графика в виде столбиков
« Ответ #8 : 22 Июль 2014, 11:43:36 »

В классе Form2 публичная функция. В нее передаёшь указатель на массив
Код
Form2->Send....
Записан
brdm
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 59


Re: Компонент для создания графика в виде столбиков
« Ответ #9 : 22 Июль 2014, 12:23:03 »

Всеравно не понимаю.
Сделал так:
Unit1.h
Код
....
public:
long *ResMass
 
Unit1.cpp
Код
long *ResMass=new long[32];
В Unit1.cpp в функции включенной в поток вычисляется ResMass[32]
В Unit2.cpp
Код
long *Res;
....
Res[0] = Form1->ResMass[0];
Возникает ошибка типа Project Project1.exe raised exception class EAccsessVolation with message 'Access violation at address...
 
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Компонент для создания графика в виде столбиков
« Ответ #10 : 22 Июль 2014, 12:27:03 »

Не судьба по-человечески объявить статический массив?
Код
long ResMass[32];
Записан
brdm
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 59


Re: Компонент для создания графика в виде столбиков
« Ответ #11 : 22 Июль 2014, 12:41:08 »

Сделал так:
Unit1.h

Код
....public:
long ResMass[32]
 
Unit1.cpp

Код
long *ResMass=new long[32];
В Unit1.cpp в функции включенной в поток вычисляется ResMass[32]
В Unit2.cpp

Код
long *Res;
.... Res = Form1->ResMass;
Ошибки не возникает, но данные не передаются.
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Компонент для создания графика в виде столбиков
« Ответ #12 : 22 Июль 2014, 12:45:26 »

Фух... не надо никакого
long *ResMass=new long[32];

Объявил статический массив и харе.
А для другой формы массив лучше не расшаривать (в приват надо убрать) и отдавать данные через функцию.

Т.е. или юнит2 имеет что-то типа SetArray(long array[])
или юнить1 имеет long *GetArray()
Записан
brdm
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 59


Re: Компонент для создания графика в виде столбиков
« Ответ #13 : 22 Июль 2014, 12:54:16 »

С функциями я всеравно без примерного кода пока не врубаюсь.
Для проверки разместил в
Код
__fastcall TForm1::TForm1(TComponent* Owner)
       : TForm(Owner)
{
   ResMass[0] = 150;
   ResMass[1] = 250;
...

В Unit2.cpp
Код
long *Res;
.... Res = Form1->ResMass;

Все работает нормально.
Получается, что массив который заполняется в функции потока потом недоступен для другой формы. Пробовал также в функциитаймера - то же самое массив не передается.
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Компонент для создания графика в виде столбиков
« Ответ #14 : 22 Июль 2014, 13:04:39 »

Если это совсем прям другой поток (thread), то могут быть проблемы.. не всё в vcl потоконезависимое (форма же vcl-льная).
Но ты слово "поток" по-моему как-то не так используешь.
У тебя две формы? В одной данные формируются, в другой - используются? Тут все должно работать. "Залез прям в форму" и обратился к элементами массива.
Но если эта другая ("использующая") форма не знает момент когда данные готовы и корректны, то надо как-то об этом сигнализировать.
Например, вызвать функцию "использующей" формы, передав в неё в качестве параметра указатель на массив (просто имя массива, никаких звездочек). Она тогда и отреагирует как-то на появление новых данных.. отрисует их к примеру.
Записан
brdm
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 59


Re: Компонент для создания графика в виде столбиков
« Ответ #15 : 22 Июль 2014, 15:05:08 »

Участок кода  Unit1.cpp
Код
...
 
#pragma link "CSPIN"
#pragma resource "*.dfm"
TForm1 *Form1;
 
long *ResMass = (long*)new long[32];
 
...
//---------------------------------------------------------------------------
// Прототипы функций
 
// тут функция принятия пакетов
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
// тут БПФ функция
void FFT(register double *x,register double *y,register int N,register int I);
 
//---------------------------------------------------------------------------
// Функции
 
// поток pcap
DWORD WINAPI Input_thread( LPVOID lpParam )
{
 pcap_loop(adhandle, 0, packet_handler, NULL);
 return 0;
}
 
//---------------------------------------------------------------------------
// приемник пакетов
 
double *x,*y;
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
 // вспомогательные строки
 AnsiString StrTmpPct, StrTmp, StrTmpFft;
 int j;
 
 // ввод строки ожидаемого мак
StrMac = Form1->ComboBox2->Text;
 // очистка проверочной строки мак
 StrMacWt = "";
 
// запись входящего мак
for(int i=0; i6; i++)
 StrMacWt += StrTmpPct.sprintf("%.2x", pkt_data[i]);
 
// проверка на входящий мак
 if(StrMacWt == StrMac && !StepOne)
{
   StrMacSh = StrMacWt;
   // нужный пакет принят
   StepOne = true;
   // начальнгое значение счетчика слов
   j = 16;
   // очистка строк
   StrPct = "";
   StrRe = "";
   StrIm = "";
   StrFft = "";
 
   for(unsigned int i=1; (i header->caplen + 1 ) ; i++)
   {
     spch.push_back(pkt_data[i - 1]);
     // запись принятого пакета в строку InPct
     StrPct += StrTmpPct.sprintf("%.2x  ", spch[i-1]);
 
     // запись принятых данных  в буфер
     if(i > 15)
     {
       sp.push_back((pkt_data[j] 8) | pkt_data[j+1]);
       if(i > (47 + Nb) && i (80 + Nb))
       {
         A[i - (48 + Nb)] = sp[i];
         //StrRe += StrTmp.sprintf("%0.4x ", sp[i]);
         StrRe += StrTmp.sprintf("%d ", A[i - (48 + Nb)]);
       }
       else if(i > (79 + Nb) && i (112 + Nb))
       {
         B[i - (80 + Nb)] = sp[i];
         //StrIm += StrTmp.sprintf("%0.4x ", sp[i]);
         StrIm += StrTmp.sprintf("%d ", B[i - (80 + Nb)]);
       }
       else if(i > (111 + Nb) && i (144 + Nb))
       {
         C[i - (112 + Nb)] = sp[i];
         //StrIm += StrTmp.sprintf("%0.4x ", sp[i]);
         //StrIm += StrTmp.sprintf("%d ", C[i - (112 + Nb)]);
       }
       j++;
       j++;
     }
   }
   for(int n = 0; n 32; n++)
   {
     if(n 16)
     {
     R[n] = (double)B[n];
     I[n] = (double)C[n];
     //R[n] = cos((n)*pi*Dgr/180)*1024;
     //I[n] = sin((n)*pi*Dgr/180)*1024;
     }
     else
     {
       R[n] = ((double)B[n] + (double)A[n])*0.707;
       I[n] = ((double)C[n] + (double)B[n])*0.707;
       //R[n] = cos((n)*pi*Dgr/180)*1024;
       //I[n] = sin((n)*pi*Dgr/180)*1024;
     }
   }
   // FFT
   x = new double();
   y = new double();
   //ResMass=new long[32];
   x=R;
   y=I;
   //сама функция бпф
   FFT(&x[0],&y[0],32,1);
   for(int k = 0; k 32; k++)
   {
     double Re = x[k];
     double Im = y[k];
   long result = 2.0 *sqrt(Re * Re + Im * Im)/(double)32;
     ResMass[k] = result;
   //StrFft += StrTmpFft.sprintf("%0.4d ", result);
   StrFft += StrTmpFft.sprintf("%0.4d ", ResMass[k]);
 }
   ResMass[0] = 150;
   ResMass[1] = 250;
 }
 Sleep(1);
}
 
//---------------------------------------------------------------------------
// бпф
 
void FFT(register double *x,register double *y,register int N,register int I)
{
   register double c,s,t1,t2,t3,t4,u1,u2,u3;
   register int i,j,p,l,L,M,M1,K;
   L=N;
   M=N/2;
   M1=N-1;
 
   while (L>=2)
   {
     l=L/2; u1=1.; u2=0.; t1=M_PI/(double)l;
     c=cos(t1); s=(-1)*I*sin(t1);
     for (j=0; jl;j++)
     {
       for (i=j; i N ;i+=L)
       {
         p=i+l;
         t1=*(x+i)+*(x+p);
         t3=*(x+i)-*(x+p);
 
         t2=*(y+i)+*(y+p);
         t4=*(y+i)-*(y+p); //
 
         *(x+i)=t1;
         *(x+p)=t3*u1-t4*u2;
 
         *(y+i)=t2;
         *(y+p)=t4*u1+t3*u2;
       }
       u3=u1*c-u2*s;
       u2=u2*c+u1*s;
       u1=u3;
     }
     L/=2;
   }
   j=0;
   for (i=0;iM1;i++)
   {
     if (i > j)
     {
       t1=*(x+j);
       t2=*(y+j);
       *(x+j)=*(x+i);
       *(y+j)=*(y+i);
       *(x+i)=t1;
*(y+i)=t2;
     }
     K=M;
     while (j >=K)
     {
       j-=K;
   K/=2;
   }
 j+=K;
   }
 
}
 
//---------------------------------------------------------------------------
// main
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
       : TForm(Owner)
{
 Sleep(50);
 if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
   Memo1->Lines->Add("Невозможно установить соеденение");
 }
else
 {
   Memo1->Lines->Add("программа открыта");
 }
 for(d=alldevs;d;d=d->next)
{
   ++i_p;
   ComboBox1->Items->Add(IntToStr(i_p)+ " " + d->description);
}
 
 hEvent1 = CreateEvent( NULL, FALSE, TRUE, NULL );
 
...
А вот запуск потока
Код
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 /******************************************************/
int inum=ComboBox1->ItemIndex+1;
AnsiString nazv = ComboBox1->Text;
 
for(d=alldevs, i_p=0; i_p inum-1 ;d=d->next, i_p++);
if ( (adhandle=pcap_open_live(d->name,65354,1,1000,errbuf)) == NULL)
 {
 Memo1->Lines->Add("Невозможно открыть адаптер!");
 }
else Memo1->Lines->Add("Выбранный вами адептер "+ nazv + " открыт для принятия пакетов!");
 
 Sleep(10);
 
 //*********создание потока приема******************
 Handle_input = CreateThread( NULL, 0,Input_thread, &Handle_thread_input, CREATE_SUSPENDED, NULL);
 if ( Handle_input == NULL) ExitProcess(Handle_thread_input);
 // разрешение таймера
 Timer1->Enabled = true;
 
 //запуск потока для принятия пакетов с помощью pcap
 ResumeThread(Handle_input);
 Sleep(10);
 
}
 
Передаю данные в Unit2 так
Код
long *Res;
....
Res = Form1->ResMass;

ResMass[0] = 150;
ResMass[1] = 250;
это для проверки передачи данных в другой модуль.
Записан
brdm
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 59


Re: Компонент для создания графика в виде столбиков
« Ответ #16 : 22 Июль 2014, 16:20:00 »

Может моя ошибка, что я пытаюсь развернуть данные в создателе формы?

Код
void __fastcall TForm2::FormCreate(TObject *Sender)
{
 Res = Form1->ResMass;
 
Series1->Clear();
......
 
Записан
brdm
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 59


Re: Компонент для создания графика в виде столбиков
« Ответ #17 : 23 Июль 2014, 20:24:01 »

Спасибо за обсуждение. Вроде получилось. Использовал вектор типа

Код
public:
.....
std::vectorlong>ResMass;
С его помощью данные передаются из модуля в модуль нормально.
Есть еще одна задачка: нарисовать график. Данные поступают дискретно (по таймеру) с частотой 100мс.
Каждый дискрет данные необходимо отобразить точкой на ситеме координат XY. Следующий дискрет тоже точкой но со сдвигом вправо и так далее. Количество дискретов конечно.

Как примерно (в коде) это можно сделать на базе TChart?   
Записан
POV
Участник


Сказали спасибо: +107/-7
Offline

Сообщений: 640


Re: Компонент для создания графика в виде столбиков
« Ответ #18 : 23 Июль 2014, 20:52:45 »

Цитата: brdm от 23 Июль 2014, 20:24:01
Как примерно (в коде) это можно сделать на базе TChart?   

Я ж выше написал как. Ты ответил, что всё получилось )
Записан
brdm
Участник


Сказали спасибо: +0/-0
Offline

Сообщений: 59


« Ответ #19 : 23 Июль 2014, 21:01:39 »

Да, график столбиками получился. Там были данные 32 точек БПФ полученные за один такт. Теперь нужно построить график по точкам полученным за много последовательных тактов

А... врубился. Спасибо. Это будет то же самое. Смещением будет получение каждой новой точки по каждому новому дискрету.    
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  




....

Powered by SMF 1.1.21 | SMF © 2025, Simple Machines
Страница сгенерирована за 0.224 секунд. Запросов: 19.