Outro módulo para desenhar gráficos

Quinze anos atrás, demorei para exibir um gráfico em meu programa de diploma. Haveria um programa no Builder ou Delphi, tudo ficaria bem, mas eu só escrevi para Windows no MFC, e aí de alguma forma não é muito bom com classes de gráfico. E então escrevi meu próprio módulo de plotagem. Passaram-se três e cinco anos, mas o módulo permaneceu, foi redesenhado e às vezes o uso em meus trabalhos em QNX, Linux e Windows. Talvez seja útil para você de alguma forma.



O módulo de desenho gráfico apresentado permite que você exiba um número arbitrário de gráficos coloridos com uma legenda. O número de pontos nos gráficos pode ser dezenas de milhões ou mais (se houver memória suficiente) sem uma diminuição significativa na velocidade de redesenho, pois cada vez que a escala é alterada, um conjunto de pontos é construído, exibido no tela, levando em consideração a escala. Assim, o número de pontos afeta apenas o tempo de recálculo desses pontos exibidos ao alterar a escala.



As funções de rasterização foram movidas para classes de plug-in. No total, três opções são atualmente possíveis: desenho com funções Windows-GUI padrão do MFC (classe CVideo_Windows), desenho com funções Qt padrão (classe CVideo_Qt) e rasterização de software (classe CVideo_Software - com revisão, este módulo pode ser usado em microcontroladores). A transcodificação de caracteres no formato exigido para classes de rasterização é realizada pela classe CTranslator.



Classes separadas incluem tipos de linha (se o tipo for compatível com a classe de rasterização), cores, pontos, retângulos.



Ao manter pressionado o botão esquerdo do mouse, você pode mover-se pelo campo do gráfico. Com o botão direito, pode definir a área selecionada, clicando sobre a qual com o botão direito do mouse você retornará à escala inicial especificada, e após clicar com o botão esquerdo, será realizada a operação de ampliação.



Os gráficos desenhados têm a seguinte aparência: A







criação de uma classe de gráfico, por exemplo, para Windows no MFC, é feita da seguinte maneira:



 CWnd_Graphics cWnd_Graphics;// 
 CGrData *cGrData_SinPtr;//    
 CGrData *cGrData_CosPtr;//    

// 
CRect cRect_Client;
((CStatic*)GetDlgItem(IDC_STATIC_MAIN_MAP))->GetClientRect(&cRect_Client);
cWnd_Graphics.Create(WS_VISIBLE,cRect_Client,(CStatic*)GetDlgItem(IDC_STATIC_MAIN_MAP));
 	
 // 
 cWnd_Graphics.GetIGraphicsPtr()->SetBackGroundColor(CGrColor(192,192,192));
 cWnd_Graphics.GetIGraphicsPtr()->SetLegendBackGroundColor(CGrColor(230,230,230));
 cWnd_Graphics.GetIGraphicsPtr()->SetAxisColor(CGrColor(0,0,0),CGrColor(0,0,0));
 cWnd_Graphics.GetIGraphicsPtr()->SetTextValueColor(CGrColor(0,0,0),CGrColor(0,0,0),CGrColor(0,0,0));
 cWnd_Graphics.GetIGraphicsPtr()->SetSelectRectangleColor(CGrColor(0,0,255)); 
 cWnd_Graphics.GetIGraphicsPtr()->SetName(" ");
 // 
 cGrData_SinPtr=cWnd_Graphics.GetIGraphicsPtr()->AddNewGraphic();
 cGrData_SinPtr->SetEnable(true);
 cGrData_SinPtr->SetGrColor(CGrColor(255,0,0));
 cGrData_SinPtr->SetGrLineStyle(CGrLineStyle(IVideo::LINE_TYPE_SOLID,1,false,false));
 cGrData_SinPtr->SetName(" ");
 
 for(size_t n=0;n<1024;n++)
 {
  double x=n;
  double y=sin(x*0.01);
  cGrData_SinPtr->AddPoint(x,y);
 }

 cGrData_CosPtr=cWnd_Graphics.GetIGraphicsPtr()->AddNewGraphic();
 cGrData_CosPtr->SetEnable(true);
 cGrData_CosPtr->SetGrColor(CGrColor(0,0,255));
 cGrData_CosPtr->SetGrLineStyle(CGrLineStyle(IVideo::LINE_TYPE_SOLID,3,false,false));
 cGrData_CosPtr->SetName(" ");

 for(size_t n=0;n<1024;n++)
 {
  double x=n;
  double y=cos(x*0.01);
  cGrData_CosPtr->AddPoint(x,y);
 }

 // ,    
 CGrRect cGrRect;
 cWnd_Graphics.GetIGraphicsPtr()->FindViewRectangle(cGrRect);
 cWnd_Graphics.GetIGraphicsPtr()->SetRectangle(cGrRect);
 cWnd_Graphics.GetIGraphicsPtr()->OnMagnify();
 cWnd_Graphics.GetIGraphicsPtr()->GetRectangle(cGrRect);
 cWnd_Graphics.GetIGraphicsPtr()->SetOriginalScale(cGrRect);

      
      





Aqui, a classe cWnd_Graphics fornece uma ligação da classe gráfica CGraphics com o Windows, encaminhando eventos que ocorrem no Windows para a classe CGraphics e fornecendo a exibição do gráfico no evento de redesenho ON_WM_PAINT. Para outros sistemas operacionais, este pacote precisará ser reescrito, levando em consideração o sistema operacional usado. Neste exemplo, por meio de cWnd_Graphics.GetIGraphicsPtr (), você pode acessar diretamente a classe do gráfico CGraphics e configurar os parâmetros de exibição do gráfico, bem como pedir à classe do gráfico para criar um novo gráfico e retornar o ponteiro AddNewGraphic para ele (um ponteiro para o A classe CGrData será obtida). Você não pode excluir este ponteiro - o gráfico pode ser excluído apenas por meio da função DeleteGraphic. No futuro, o trabalho com a programação é executado por meio do ponteiro resultante.



No total, as seguintes funções de gerenciamento de gráfico estão disponíveis:



CGrData* AddNewGraphic(void);//       
  void DeleteAllGraphics(void);//    
  void DeleteGraphic(CGrData *cGrDataPtr);//   
  void FindRectangle(CGrRect &cGrRect) const;//     
  void FindRectangleOfEndPoints(CGrRect &cGrRect,size_t points) const;//        points 
  void FindRectangleOfEndTime(CGrRect &cGrRect,long double time) const;//        time 
  void FindViewRectangle(CGrRect &cGrRect) const;//         
  void FindViewRectangleOfEndPoints(CGrRect &cGrRect,size_t points) const;//            points 
  void FindViewRectangleOfEndTime(CGrRect &cGrRect,long double time) const;//            time 
  void SetTimeDivider(double value);//  
  double GetTimeDivider(void) const;//  
  // 
  void CancelSelect(void);// 
  void Redraw(void);// 
  void RedrawAll(void);// 
  void OnOriginalScale(void);//    
  //  
  void SetBackGroundColor(const CGrColor &cGrColor);//  
  void SetLegendBackGroundColor(const CGrColor &cGrColor);//   
  void SetAxisColor(const CGrColor &cGrColor_AxisX,const CGrColor &cGrColor_AxisY);//  
  void SetGridColor(const CGrColor &cGrColor_GridX,const CGrColor &cGrColor_GridY);//  
  void SetSelectRectangleColor(const CGrColor &cGrColor);//   
  void SetTextValueColor(const CGrColor &cGrColor_TextX,const CGrColor &cGrColor_TextY,const CGrColor &cGrColor_TextLegend);//  
  //   
  void SetAxisLineStyle(const CGrLineStyle &cGrLineStyle_AxisX,const CGrLineStyle &cGrLineStyle_AxisY);//  
  void SetGridLineStyle(const CGrLineStyle &cGrLineStyle_GridX,const CGrLineStyle &cGrLineStyle_GridY);//  
  //   
  void SetRectangle(const CGrRect &cGrRect);//   
  void SetGridStep(long double step_x,long double step_y);//  
  void GetRectangle(CGrRect &cGrRect) const;//   
  void GetGridSize(long double &step_x,long double &step_y) const;//   
  //  
  void SetEnableMagnify(bool enable);// 
  void SetEnableValue(bool x_value,bool y_value);//  
  void SetOriginalScale(const CGrRect &cGrRect);//  
  void SetMoveMode(bool inversion);//   
  bool GetSelectedRectangle(CGrRect &cGrRect) const;//  
  void GetClientRectangle(CGrRect &cGrRect) const;//  
  void SetName(const std::string &name);//  
  bool GetUserMode(void) const;//   
  void SetUserMode(bool state);//   

      
      





Em princípio, você pode personalizar a tela de forma bastante flexível.



O modo de controle do usuário especificado nas duas últimas funções é usado ao enviar dados com atualizações (digamos, o instrumento adiciona pontos em alguma frequência). Neste caso, ao tentar mover / ampliar o gráfico, o modo de controle do usuário é habilitado, e quando você retorna à escala original, este modo é desabilitado. Isso permite que você pare de alterar a escala enquanto adiciona dados (se o modo estiver habilitado, você simplesmente não precisa chamar o recálculo da escala, como no exemplo acima).



Um exemplo de programa usando este módulo (existem fontes do módulo).

Existem 4 arquivos do projeto - main.cpp, cdialog_main.h, cdialog_main.cpp e stdafx.h. Esses quatro arquivos contêm um exemplo de conexão do módulo de plotagem. Todos os outros arquivos de origem são partes do módulo de plotagem.



Bem, isso é realmente tudo o que pode ser dito sobre esta nave primitiva.

PS Fui avisado aqui que eu tinha um nome infeliz para as funções (Gráfico - gráfico e Gráfico - gráfico). Desculpe, aprendi alemão e pensei que em inglês seria assim. :)



All Articles