/*# --------------------------------------------------------------------- # # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image # pour la Sant�) # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton # Previous Authors : Laurent Guigues, Jean-Pierre Roux # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil # # This software is governed by the CeCILL-B license under French law and # abiding by the rules of distribution of free software. You can use, # modify and/ or redistribute the software under the terms of the CeCILL-B # license as circulated by CEA, CNRS and INRIA at the following URL # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html # or in the file LICENSE.txt. # # As a counterpart to the access to the source code and rights to copy, # modify and redistribute granted by the license, users are provided only # with a limited warranty and the software's author, the holder of the # economic rights, and the successive licensors have only limited # liability. # # The fact that you are presently reading this means that you have had # knowledge of the CeCILL-B license and that you accept its terms. # ------------------------------------------------------------------------ */ //---------------------------------------------------------------- #ifdef __GNUG__ #pragma implementation "chart.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif //------------------------------------------------------------------- #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "chart.h" #include //---------------------------------------------------------------- // DataSet : Constructor & Destructor //------------------------------------------------------------------- wxDataSet::wxDataSet(wxPen *lStyle, wxBrush *dStyle, int dWidth, int lWidth, int dGap, int pMark, int disValues) { m_lineStyle = lStyle; m_dataStyle = dStyle; m_dataWidth = dWidth; m_lineWidth = lWidth; m_pointMark = pMark; m_displayValues = disValues; m_display = false; m_rowsList = NULL; m_text = NULL; } wxDataSet::wxDataSet(wxPen *lStyle, wxBrush *dStyle, wxString *lText, bool lDisplay) { m_lineStyle = lStyle; m_dataStyle = dStyle; m_display = lDisplay; m_text = lText; m_rowsList = NULL; m_dataWidth = 0; m_lineWidth = 0; m_pointMark = 0; m_displayValues = 0; } wxDataSet::wxDataSet() { m_lineStyle = NULL; m_dataStyle = NULL; m_dataWidth = 0; m_lineWidth = 0; m_pointMark = 0; m_displayValues = 0; m_display = false; m_rowsList = NULL; m_text = NULL; } wxDataSet::~wxDataSet() { // Nothing } //----------------------------------------------------------------- // Chart //------------------------------------------------------------------- BEGIN_EVENT_TABLE(wxChart, wxWindow) EVT_PAINT(wxChart::OnPaint) END_EVENT_TABLE() //--------------------------------------------------------------------- // Constructor & Destructor wxChart::wxChart(wxFrame *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxWindow(parent, id, pos, size, style, name) { SetMaxWidthHeight(size.GetWidth(), size.GetHeight()); SetCenterChart(pos.x + (GetLargeur()/2), pos.y + (GetHauteur()/2)); InitDataSet(); InitChart(); } wxChart::~wxChart() { // nothing } void wxChart::InitChart() { SetShowPer(false); //not display line % per default for(int i=0; i 1) { if ( result.rem == 0 ) { if (val - (int)val > 0 ) retour = (multi - result.rem) - (val - int(val)); } else { retour = (multi - result.rem) - (val - int(val)); } } } // multiple inf else retour = result.rem + (val - (int)val); return retour; } static double st_decalage(double IncX, double MinX) { double retour = 0.00; div_t result; if (IncX >= 1) { result = div(MinX, IncX); if ( result.rem == 0 ) { if (MinX - (int)MinX > 0 ) retour = ((result.quot + 1) * IncX) - MinX; } else { retour = ((result.quot+1) * IncX) - MinX; } } return retour; } static double st_origine(double IncX, double MinX) { double retour = MinX; div_t result; if (IncX >=1) { result = div(MinX, IncX); if (result.rem == 0) { if (MinX - (int)MinX > 0 ) retour = (result.quot + 1) * IncX; } else { retour = (result.quot + 1) * IncX; } } return retour; } static void st_InverseCol(double *l_MinCol, double *l_MaxCol) { if (*l_MinCol > *l_MaxCol) { int tempo = *l_MaxCol; *l_MaxCol = *l_MinCol; *l_MinCol = tempo; } } //-------------------------------------------------------------- void wxChart::SetInfX(double inf) { m_InfX = inf; } void wxChart::SetSupX(double sup) { m_SupX = sup; } void wxChart::SetSupY(double sup) { m_SupY = sup; } void wxChart::SetIncAxisX(double minor, double major) { m_MinorIncX = minor; m_MajorIncX = major; } void wxChart::SetIncAxisY(double minor, double major) { m_MinorIncY = minor; m_MajorIncY = major; } void wxChart::SetInitEdge() { SetEdgeTop(15); SetEdgeBottom(35); SetEdgeLeft(37); SetEdgeRight(15); } void wxChart::SetChartBounds() { m_Top = m_CenterY - (m_MaxHauteur/2) + m_EdgeTop; m_Bottom = m_CenterY + (m_MaxHauteur/2) - m_EdgeBottom; m_Left = m_CenterX - (m_MaxLargeur/2) + m_EdgeLeft; m_Right = m_CenterX + (m_MaxLargeur/2) - m_EdgeRight; } void wxChart::SetChartBoundsLegend() { m_TopLegend = m_CenterY - (m_MaxHauteur/2) + m_EdgeTopLegend; m_BottomLegend = m_CenterY + (m_MaxHauteur/2) - m_EdgeBottomLegend; m_LeftLegend = m_CenterX - (m_MaxLargeur/2) + m_EdgeLeftLegend; m_RightLegend = m_CenterX + (m_MaxLargeur/2) - m_EdgeRightLegend; } void wxChart::SetCadreLegend(int nbr, int *bottom) { int val=GetEdgeBottom(); div_t result = div(nbr, 2); if (result.rem == 0) val+= (nbr * 10) + 5; else val+= (( nbr + 1 ) * 10) + 5; *bottom = val; SetEdgeTopLegend(m_CenterY + (m_MaxHauteur/2) - val + 33); SetEdgeBottomLegend(8); int l_left = GetEdgeLeft(); int l_right = GetEdgeRight(); // more small for only 1 line if (nbr == 1) { l_left+=m_CenterX - (m_MaxLargeur/3); l_right+=m_CenterX - (m_MaxLargeur/3); } SetEdgeLeftLegend(l_left); SetEdgeRightLegend(l_right); } void wxChart::SetShowPer(bool per) { m_ShowPer = per; } void wxChart::SetMaxValue(double max) { // Axe Y m_MaxValue = max; } double wxChart::MaxValue() { double data, val = 1.00; int maxdata = GetNumDataSet()-1; int maxitem = GetNumItem(); // Exclure Stenosis for calcul MaxValue for(int a=0; a < maxdata; a++) { if (GetShowDataSet(a)) { for(int j=0; j<=maxitem; j++) { if ( IsEmpty(a,j) == false ) { data = GetDataY(a,j); if (data > val) val = data; } } } } return val; } double wxChart::MinCol(double min) { double retour = 0.00; int maxdata = GetNumDataSet()-1; // Exclure Stenosis for calcul MaxValue for(int a=0; a < maxdata; a++) { if (GetShowDataSet(a)) { if (min > retour) retour = min; a = maxdata - 1; } } return retour; } double wxChart::MaxCol(double max) { double retour = 1.00; int maxdata = GetNumDataSet()-1; // Exclure Stenosis for calcul MaxValue for(int a=0; a < maxdata; a++) { if (GetShowDataSet(a)) { if (max > retour) retour = max; a = maxdata - 1; } } return retour; } void wxChart::SetStepSizeX(double stepX) { m_StepSizeX = stepX; } void wxChart::SetStepSizeY(double stepY) { m_StepSizeY = stepY; } void wxChart::SetStepSizePer(double stepPer) { m_StepSizePer = stepPer; } void wxChart::SetCenterChart(int x, int y) { m_CenterX = x; m_CenterY = y; } void wxChart::SetMaxWidthHeight(int x,int y) { m_MaxLargeur = x; m_MaxHauteur = y; } void wxChart::SetMinX(double MinX) { m_MinX = MinX; } void wxChart::SetMaxX(double MaxX) { m_MaxX = MaxX; } void wxChart::SetEdgeTop(int top) { m_EdgeTop = top; } void wxChart::SetEdgeBottom(int bottom) { m_EdgeBottom = bottom; } void wxChart::SetEdgeLeft(int left) { m_EdgeLeft = left; } void wxChart::SetEdgeRight(int right) { m_EdgeRight = right; } void wxChart::SetEdgeTopLegend(int top) { m_EdgeTopLegend = top; } void wxChart::SetEdgeBottomLegend(int bottom) { m_EdgeBottomLegend = bottom; } void wxChart::SetEdgeLeftLegend(int left) { m_EdgeLeftLegend = left; } void wxChart::SetEdgeRightLegend(int right) { m_EdgeRightLegend = right; } void wxChart::SetNumDataSet(int num) { m_NumDataSet = num; } void wxChart::SetNumItem(int num) { m_NumItem = num; } int wxChart::GetShow() { int retour = 0; for(int i=0; i < m_NumDataSet ; i++) { if (GetShowDataSet(i)) retour++; } return retour; } void wxChart::InitDataSet() { // Initialization SetNumDataSet(8); for(int i=0; i 0) { SetCadreLegend(nbr, &m_EdgeBottom); SetChartBoundsLegend(); DrawLegend(dc, nbr); } //------------------------------------------------------------------- // Valeur Min et Max des abscisses SetMinX(MinCol(0)); SetMaxX(MaxCol(1)); SetInfX(st_difference(m_MinX,10,false)); SetSupX(st_difference(m_MaxX,10,true)); //------------------------------------------------------------------ // Data // Stenosis SetNumItem(6); SetData(wxStenosis, 0, 0, -45); SetData(wxStenosis, 1, 0.4, 0); SetData(wxStenosis, 2, 0.6, -15); SetData(wxStenosis, 3, 0.8, 0); SetData(wxStenosis, 4, 0.9, 100); SetData(wxStenosis, 5, 1, 0); // Area SetData(wxArea,0, 0, 0.8); SetData(wxArea,1, 0.2, 0.6); SetData(wxArea,2, 0.3, 0.8); SetData(wxArea,3, 0.4, 1); SetData(wxArea,4, 0.8, 0.4); SetData(wxArea,5, 1, 0.2); //----------------------------------------------------------------- // Valeur Max du chart SetMaxValue(MaxValue()); SetSupY(st_difference(m_MaxValue, 10, true)); //------------------------------------------------------------------------------- // Scale SetIncAxisX((m_MaxX + m_SupX - (m_MinX - m_InfX)) / (double)MINOR_STEP, (m_MaxX + m_SupX - (m_MinX - m_InfX)) / (double)MAJOR_STEP); SetIncAxisY((m_MaxValue + m_SupY) / (double)MINOR_STEP, (m_MaxValue + m_SupY) / (double)MAJOR_STEP); SetStepSizeX(( m_MaxLargeur - (m_EdgeLeft + m_EdgeRight + m_SupX + m_InfX)) / (m_MaxX - m_MinX)); SetStepSizeY(( m_MaxHauteur - (m_EdgeBottom + m_EdgeTop + m_SupY )) / (m_MaxValue)); SetStepSizePer(( m_MaxHauteur - (m_EdgeBottom + m_EdgeTop)) / (double)MAX_PER); //----------------------------------------------------------------------------- // Empty Chart //--------------------------------------------------------------------------- SetChartBounds(); DrawGrille(dc); DrawAxe(dc); if (m_ShowPer) DrawAxePer(dc); //----------------------------------------------------------------------------- // Clipping //--------------------------------------------------------------------------- dc.DestroyClippingRegion(); dc.SetClippingRegion(m_Left , m_Top , GetLargeur() - (m_EdgeRight + m_EdgeLeft ), GetHauteur() - (m_EdgeTop + m_EdgeBottom )); //--------------------------------------------------------------------------- // Draw line //--------------------------------------------------------------------------- int maxdataset = GetNumDataSet(); for(int a=0; a < maxdataset; a++) { if(m_dataSetArray[a] && m_dataSetArray[a]->GetShow()) { dataBrush = m_dataSetArray[a]->GetDataStyle(); dataPen = m_dataSetArray[a]->GetLineStyle(); dc.SetBrush(*dataBrush); dc.SetPen(*dataPen); DrawLine(dc, a); } } //--------------------------------------- // end dc.DestroyClippingRegion(); dc.EndDrawing(); } void wxChart::DrawAxe(wxDC& dc) { double x,y; double val, supx; char text[20]; int widthx,heighty; double minorIncStepY= m_MinorIncY * m_StepSizeY; double majorIncStepY= m_MajorIncY * m_StepSizeY; double minorIncStepX= m_MinorIncX * m_StepSizeX; double majorIncStepX= m_MajorIncX * m_StepSizeX; dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxBLACK_BRUSH); // Axe X dc.DrawLine(m_Left, m_Bottom+(7*MARGE/4), m_Right, m_Bottom+(7*MARGE/4)); // Axe Y dc.DrawLine(m_Left-(7*MARGE/4), m_Bottom, m_Left-(7*MARGE/4), m_Top); // AXE Y // Major Tick Marks with values val=0.00; for(x=m_Left,y=m_Bottom; y >= m_Top; y-=majorIncStepY, val+=m_MajorIncY) { dc.DrawLine(m_Left-7-(7*MARGE/4),y,m_Left-(7*MARGE/4),y); sprintf(text,"%g", val); dc.GetTextExtent(text,&widthx,&heighty); dc.DrawText(text,m_Left-10-widthx-(7*MARGE/4),y-(heighty/2)); } // Ne pas Depasser if (m_SupY == 0 ) { dc.DrawLine(m_Left-7-(7*MARGE/4),m_Top,m_Left-(7*MARGE/4),m_Top); sprintf(text,"%g", val); dc.GetTextExtent(text,&widthx,&heighty); dc.DrawText(text,m_Left-10-widthx-(7*MARGE/4),m_Top-(heighty/2)); } // Minor Tick Marks for(x=m_Left,y=m_Bottom; y >= m_Top; y-=minorIncStepY) { dc.DrawLine(m_Left-3-(7*MARGE/4),y,m_Left-(7*MARGE/4),y); } // AXE X // Major Tick Marks with values supx = st_decalage(m_MajorIncX, m_MinX) * m_StepSizeX; val = st_origine(m_MajorIncX, m_MinX); for(y=m_Bottom,x=m_Left + supx; x <= m_Right; x+=majorIncStepX, val+=m_MajorIncX) { dc.DrawLine(x,m_Bottom+7+(7*MARGE/4),x,m_Bottom+(7*MARGE/4)); sprintf(text,"%g", val); dc.GetTextExtent(text,&widthx,&heighty); dc.DrawText(text,x-(widthx/2),y+3+heighty); } // Ne pas Depasser if ( m_SupX == 0 ) { dc.DrawLine(m_Right,m_Bottom+7+(7*MARGE/4),m_Right,m_Bottom+(7*MARGE/4)); sprintf(text,"%g", val); dc.GetTextExtent(text,&widthx,&heighty); dc.DrawText(text,m_Right-(widthx/2),m_Right+3+heighty); } supx = st_decalage(m_MinorIncX, m_MinX) * m_StepSizeX; //Minor Tick Marks for(y=m_Bottom,x=m_Left + supx; x <= m_Right; x+=minorIncStepX) { dc.DrawLine(x,m_Bottom+3+(7*MARGE/4),x,m_Bottom+(7*MARGE/4)); } } void wxChart::DrawAxePer(wxDC& dc) { double x,y; double val; char text[20]; int widthx,heighty; double minorIncStepPer= MINOR_PER * m_StepSizePer; double majorIncStepPer= MAJOR_PER * m_StepSizePer; dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxBLACK_BRUSH); // AXE Per dc.DrawLine(m_Right+(7*MARGE/4), m_Bottom, m_Right+(7*MARGE/4), m_Top); // Major Tick Marks with values val=0.00; for(x=m_Right,y=m_Bottom; y >= m_Top; y-=majorIncStepPer, val+=MAJOR_PER) { dc.DrawLine(m_Right+(7*MARGE/4),y,m_Right+7+(7*MARGE/4),y); sprintf(text,"%g",(val-(MAX_PER/2))); dc.GetTextExtent(text,&widthx,&heighty); dc.DrawText(text,m_Right+10+(7*MARGE/4),y-(heighty/2)); } dc.DrawLine(m_Right+(7*MARGE/4),m_Top,m_Right+7+(7*MARGE/4),m_Top); sprintf(text,"%g",(val-(MAX_PER/2))); dc.GetTextExtent(text,&widthx,&heighty); dc.DrawText(text,m_Right+10+(7*MARGE/4),m_Top-(heighty/2)); // Minor Tick Marks for(x=m_Right,y=m_Bottom; y >= m_Top; y-=minorIncStepPer) { dc.DrawLine(m_Right+(7*MARGE/4),y,m_Right+3+(7*MARGE/4),y); } } void wxChart::DrawGrille(wxDC& dc) { double x,y; double val; double minorIncStepY = m_MinorIncY * m_StepSizeY; double minorIncStepX = m_MinorIncX * m_StepSizeX; dc.SetBrush(*wxLIGHT_GREY_BRUSH); // Tracer DOT wxPen *Pen = new wxPen(*wxLIGHT_GREY, 1, wxDOT); dc.SetPen(*Pen); // quadrillage en point // axe Y for(x=m_Left,y=m_Bottom; y >= m_Top; y-=minorIncStepY) dc.DrawLine(m_Left-MARGE,y,m_Right+MARGE,y); if (m_SupY == 0) dc.DrawLine(m_Left-MARGE,m_Top,m_Right+MARGE,m_Top); // axe X val = st_decalage(m_MinorIncX, m_MinX) * m_StepSizeX; for(y=m_Bottom, x=m_Left + val ; x <= m_Right; x+=minorIncStepX) dc.DrawLine(x,m_Bottom+MARGE,x,m_Top-MARGE); if (m_SupX == 0) dc.DrawLine(m_Right,m_Bottom+MARGE,m_Right,m_Top-MARGE); // Contour Pen->SetStyle(wxSOLID); dc.SetPen(*Pen); dc.DrawLine(m_Left-MARGE, m_Top-MARGE, m_Right+MARGE, m_Top-MARGE); dc.DrawLine(m_Right+MARGE, m_Top-MARGE, m_Right+MARGE, m_Bottom+MARGE); dc.DrawLine(m_Right+MARGE, m_Bottom+MARGE, m_Left-MARGE, m_Bottom+MARGE); dc.DrawLine(m_Left-MARGE, m_Bottom+MARGE, m_Left-MARGE, m_Top-MARGE); } void wxChart::DrawLegend(wxDC& dc, int nbre) { // Init wxString *string; wxPen *dataPen; wxBrush *dataBrush; int widthx, heighty, l_posx, l_posy; char text[30]; int haut_ligne, compt = 0; int l_haut = m_BottomLegend - m_TopLegend; int l_larg = m_RightLegend - m_LeftLegend; div_t result = div(nbre,2); div_t resulta; int l_debut = 30, l_trait = 15, l_space = 10; if (result.rem == 0) haut_ligne = l_haut / result.quot; else haut_ligne = l_haut / (result.quot+1); // Contour dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxBLACK_BRUSH); dc.DrawLine(m_LeftLegend, m_TopLegend, m_RightLegend, m_TopLegend); dc.DrawLine(m_RightLegend, m_TopLegend, m_RightLegend, m_BottomLegend); dc.DrawLine(m_RightLegend, m_BottomLegend, m_LeftLegend, m_BottomLegend); dc.DrawLine(m_LeftLegend, m_BottomLegend, m_LeftLegend, m_TopLegend); // For each dataset int maxdataset = GetNumDataSet(); for (int a=0; a < maxdataset; a++) { if (m_dataSetArray[a] && m_dataSetArray[a]->GetShow()) { compt++; // Text string = m_dataSetArray[a]->GetText(); sprintf(text,"%s",string); dc.GetTextExtent(text,&widthx,&heighty); resulta = div(compt, 2); l_posx = m_LeftLegend; l_posy = m_TopLegend; if (resulta.rem == 0) { l_posx+= l_larg/2; l_posy+= (haut_ligne * resulta.quot); } else l_posy+= (haut_ligne * (resulta.quot+1)); l_posy-= (haut_ligne/2); // proportion if (nbre==1) l_posx = m_LeftLegend + ((l_larg - l_trait - l_space - widthx)/2) - l_debut; // ligne dataBrush = m_dataSetArray[a]->GetDataStyle(); dataPen = m_dataSetArray[a]->GetLineStyle(); dataPen->SetWidth(2); dc.SetBrush(*dataBrush); dc.SetPen(*dataPen); dc.DrawLine(l_posx + l_debut, l_posy, l_posx + l_debut + 15, l_posy); dataPen->SetWidth(1); // text dc.SetFont(*(new wxFont(1, wxDEFAULT, wxNORMAL, wxBOLD))); dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxBLACK_BRUSH); dc.DrawText(text,l_posx + l_debut + l_trait + l_space ,l_posy - (heighty/2)); dc.SetFont(*(new wxFont(1, wxDEFAULT, wxNORMAL, wxLIGHT))); } } } void wxChart::DrawLine(wxDC &dc, int a) { int compt=0; double val; double mid = m_Bottom - ((m_Bottom-m_Top)/2); int maxitem = GetNumItem(); float yprec, xprec; float xsuiv, ysuiv; for(int j=0; j < maxitem; j++) { if ( IsEmpty(a,j) == false ) { compt++; xsuiv = m_Left + ((GetDataX(a,j) - m_MinX ) * m_StepSizeX); val = GetDataY(a,j); if ( a == wxStenosis) // Axe Per for Stenosis ysuiv = mid - (val * m_StepSizePer); else // Axe X ysuiv = m_Bottom - (val * m_StepSizeY); // Draw line if (compt > 1) dc.DrawLine(xprec, yprec, xsuiv, ysuiv); // save point prec xprec = xsuiv; yprec = ysuiv; } } } // Click Mouse //----------------------------------------------------------------- void wxChart::OnLeftClick(wxDC &dc, double x, double y, int keys) { // TO IMPLEMENT } void wxChart::OnRightClick(wxDC &dc, double x, double y, int keys) { // TO IMPLEMENT } // Data //-------------------------------------------------------------------- void wxChart::InitData() { SetNumItem(0); for(int a=0; aShow(show); } bool wxChart::GetShowDataSet(int dataset) { if(m_dataSetArray[dataset]) return m_dataSetArray[dataset]->GetShow(); else return 1; }