Перейти к содержанию
    

Перемещение отдельного графика в TeeChart по оси Y

Всем Привет!

 

Есть ли стандартные средства перемещения и масштабирования отдельных графиков в ТеeChart?

С масштабированием группы графиков (например графики Series1, Series2, Series3 входящих в один Chart1) , проблем нет, меняются минимумы и максимумы по оси-Y у Chart1, и они и двигаются и масштабируются быстро.

Но нужно сдвинуть только один, например красный сдвинуть вверх, но чтобы зеленый остался на месте:

image.png

 

Понятно что можно математически:

for(int i=0;i<Chart1->Series[1]->Count()-1;i++)
Chart1->Series[1]->YValues->Value[i]+=Y;

Но при больших графиках, например по оси-X 690тысяч точек, такой алгоритм откровенно тормозит.

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

Уже два дня копаю TeeChart на эту тему, в нем много всего, но нужное не могу найти.

Может типа какая нибудь локальная система координат для каждого отдельного Series?

 

Есть еще один вопрос, по поводу стандартного масштабирования в TeeChart, например есть такой график:

image.png

он имеет пики 1,2,3, они очень тоненькие, но при отдалении зума они сохраняются, видно на нижнем графике, и изза этого создается впечатление что сигнал на нижнем графике сильно зашумлен, хотя там всего маленькие иголочки были. Это похоже как в осциллографе есть режим PeakDetected, но его в осциллографе можно выключить и эти тонкие пики на отдаленном по зуму сигнале отображаться не будут.

Вот вопрос: как в TeeChart тоже отключить этот режим PeakDetected, т.е. чтобы на отдаленном отображении графика эти иголочки вообще не отображались ?

Вот еще картинка для примера:

image.png

Может нестандартными средствами можно такое скрыть (без использования фильтра LowPass) ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но при больших графиках, например по оси-X 690тысяч точек, такой алгоритм откровенно тормозит.

Тормоз появляется при большом объеме данных, которые надо постоянно обрабатывать при отображении на экране.

Вопрос, зачем их обрабатывать постоянно, ведь они не изменяются ? (по крайней мере основная подавляющая их часть)

Перед отображением информации сделайте ее предв. обработку, наподобие индексации и фильтрации с формированием файлов "ускоренных" индексов, меток итд . (например, для каждого значения масштаба отображения). Тогда "тормоз" будет один раз, при первой загрузке и сканировании массива, а при масштабировании можно пользоваться ускряющими сформированными "индексными" файлами.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот сделал отображение графика как хотел, лишние иголочки не отображаются:

Сверху как было, снизу как стало:

image.png

Для вывода использовал компонент TeeChart - Color Grid - Color Range (у него обнаружилось ограничение в 32768 точек по горизонтали, поэтому мои 500тысяч точек пришлось сжимать под это размер, или в с случае pBitmap до ширины картинки, и именно 890точек)

Но предварительно данные подготавливаются, сжимаются по горизонтали и вертикали в массив Map. В принципе можно выводить и в pBitmap->Canvas->Pixels[x][y] = RGB (Map[x][255-y], Map[x][255-y], Map[x][255-y]);  а потом PaintBox1->Canvas->Draw(0,0,pBitmap);

 

Вот отладочные куски может кому пригодится:

первый это сжатие:

Spoiler

void __fastcall TForm1::Button4Click(TObject *Sender)
{

 TColor Color;
 Color=RGB (128, 128, 128);
 AnsiString astr;

 int index;
 int CanvMaxX;
int CanvMaxY;
int col, ColorMax,ColorMin,ColorRange;
double ColorStep;
double SumArray[65536];
double data_in;
//double Arr256[256];
double Val256;
//signed short map[890][256];
//int *arr = new int [100000];
//double *map = new double [890][256];
/* // этот фрагмент выполняется при создании формы, вставил сюда для общего понимания
      n=890; m=256;
	Map = new double *[n];
	for (int i = 0; i < n; ++i)
	Map[i] = new double [m];

 pBitmap = new Graphics::TBitmap();  // здесь будет рисоваться картинка, а потом перерисовываться в PaintBox1
 pBitmap->Height=PaintBox1->Height;
 pBitmap->Width=PaintBox1->Width;
 */

int flag_init=0;


CanvMaxX=PaintBox1->Width;
CanvMaxY=PaintBox1->Height;


ColorMin=TrackBar1->Position;//=128;
ColorMax=TrackBar2->Position;//255;
ColorRange=ColorMax-ColorMin;
ColorStep=(double)ColorRange/CanvMaxY;

astr="CanvMaxX=";   astr+=CanvMaxX;
astr+=" CanvMaxY="; astr+=CanvMaxY;
astr+=" ColorMin="; astr+=ColorMin;
astr+=" ColorMax="; astr+=ColorMax;
Label3->Caption=astr;

ProgressBar1->Max=890;

for (int len=0;len<890;len++)    //890 это кол-во точек на отображаемом экране
{
   // обнуляем массив SumArray
	for(int k=0;k<65536;k++) SumArray[k]=0;

   // сжимаем по горизонтали в один столбец N значений графика
		for (int i = 0; i < 584; i++) {
		   data_in=Chart1->Series[0]->YValues->Value[len*584+i];
		   for (int j = 0; j < 65536; j++) {
			   if(j<data_in) SumArray[j]+=1;
		   }

		}

		// обнуляем Val256
		Val256=0;

		// сжимаем по вертикали в 256 раз
		 for (int i = 0; i < 256; i++) {
		 for (int j = 0; j < 256; j++) {
		  index=i*256+j;
		  Val256+=SumArray[index];
		  if(index>65533)
		  int g=0;
		 }
		 Val256/=256;
		 Map[len][i]=Val256;  //        Map[890][256]
		 if(flag_init==0) { max_val=Val256; min_val=Val256; flag_init=1;}
		 else{
		   if (Val256<min_val) {min_val=Val256;}
		   if (Val256>max_val) {max_val=Val256;}

		   }
		 }


	 ProgressBar1->Position=len;
}
   astr="Min="; astr+=min_val; astr+=" Max="; astr+=max_val;
   Label6->Caption=astr;
  ProgressBar1->Position=0;

// ---------- копируем из Map в pBitmap ---------------
for(int x=0;x<890;x++)
 for (int y=0;y<256;y++)
 {
   pBitmap->Canvas->Pixels[x][y] = RGB (Map[x][255-y], Map[x][255-y], Map[x][255-y]);
 }


  PaintBox1->Canvas->Draw(0,0,pBitmap);
 
}

 

второй это вывод на экран в двух видах, в картинку BitmapCanvas и в SeriesTeeChart:

Spoiler

void __fastcall TForm1::Button5Click(TObject *Sender)
{
double val_from_map,new_delta,old_delta,val_from,val_to;

if (TrackBar2->Position > TrackBar1->Position) { val_from=TrackBar1->Position; val_to=TrackBar2->Position; }
else { val_from=TrackBar2->Position; val_to=TrackBar1->Position; }


//Series3->Clear();
// ---------- копируем из Map в pBitmap, переворачивая верх с низом ---------------
for(int x=0;x<890;x++)
 for (int y=0;y<256;y++)
 {
// double max_val, min_val;
   val_from_map=Map[x][y];
   // нормирование цвета в диапазон
   val_from_map-=min_val;
	 new_delta=val_to-val_from;
   old_delta=max_val-min_val;
   val_from_map=val_from_map*new_delta/old_delta;
   val_from_map+=val_from;

   pBitmap->Canvas->Pixels[x][255-y] = RGB (255-val_from_map, 255-val_from_map, 255-val_from_map);

   Series3->AddXYZ(x,RGB (val_from_map, val_from_map, val_from_map),y);
 }

 Label5->Caption=Map[10][TrackBar3->Position];

  PaintBox1->Canvas->Draw(0,0,pBitmap);
}

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Заменил сжатие по горизонтали более простым алгоритмом, и время обработки сократилось с 56сек до 4сек

То что закомментарено, это так было, а ниже как стало:

		  // for (int j = 0; j < 65536; j++) {
		  //	   if(j<data_in) SumArray[j]+=1;
		  // }

		   for (int j = 0; j < data_in; j++) {
			   SumArray[j]+=1;
		   }

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...