3 //----------------------------------------------------------------
5 #pragma implementation "chart.h"
12 //-------------------------------------------------------------------
13 #include "wx/wxprec.h"
22 //----------------------------------------------------------------
23 // DataSet : Constructor & Destructor
24 //-------------------------------------------------------------------
25 wxDataSet::wxDataSet(wxPen *lStyle, wxBrush *dStyle, int dWidth,
26 int lWidth, int dGap, int pMark, int disValues)
33 m_displayValues = disValues;
39 wxDataSet::wxDataSet(wxPen *lStyle, wxBrush *dStyle,
40 wxString *lText, bool lDisplay)
55 wxDataSet::wxDataSet()
69 wxDataSet::~wxDataSet()
77 //-----------------------------------------------------------------
79 //-------------------------------------------------------------------
80 BEGIN_EVENT_TABLE(wxChart, wxWindow)
81 EVT_PAINT(wxChart::OnPaint)
84 //---------------------------------------------------------------------
85 // Constructor & Destructor
86 wxChart::wxChart(wxFrame *parent, wxWindowID id,
87 const wxPoint& pos, const wxSize& size,
88 long style, const wxString& name)
89 : wxWindow(parent, id, pos, size, style, name)
92 SetMaxWidthHeight(size.GetWidth(), size.GetHeight());
93 SetCenterChart(pos.x + (GetLargeur()/2), pos.y + (GetHauteur()/2));
109 void wxChart::InitChart()
111 SetShowPer(false); //not display line % per default
113 for(int i=0; i<m_NumDataSet ; i++)
114 ShowDataSet(false, i);
122 //--------------------------------------------------------------
123 static double st_difference(double val, int multi, bool sens=true)
128 result = div(int(val), multi);
134 if ( result.rem == 0 )
136 if (val - (int)val > 0 )
137 retour = (multi - result.rem) - (val - int(val));
141 retour = (multi - result.rem) - (val - int(val));
147 retour = result.rem + (val - (int)val);
152 static double st_decalage(double IncX, double MinX)
154 double retour = 0.00;
159 result = div(MinX, IncX);
160 if ( result.rem == 0 )
162 if (MinX - (int)MinX > 0 )
163 retour = ((result.quot + 1) * IncX) - MinX;
167 retour = ((result.quot+1) * IncX) - MinX;
174 static double st_origine(double IncX, double MinX)
176 double retour = MinX;
181 result = div(MinX, IncX);
184 if (MinX - (int)MinX > 0 )
185 retour = (result.quot + 1) * IncX;
189 retour = (result.quot + 1) * IncX;
196 static void st_InverseCol(double *l_MinCol, double *l_MaxCol)
198 if (*l_MinCol > *l_MaxCol)
200 int tempo = *l_MaxCol;
201 *l_MaxCol = *l_MinCol;
208 //--------------------------------------------------------------
209 void wxChart::SetInfX(double inf)
214 void wxChart::SetSupX(double sup)
220 void wxChart::SetSupY(double sup)
227 void wxChart::SetIncAxisX(double minor, double major)
233 void wxChart::SetIncAxisY(double minor, double major)
240 void wxChart::SetInitEdge()
250 void wxChart::SetChartBounds()
252 m_Top = m_CenterY - (m_MaxHauteur/2) + m_EdgeTop;
253 m_Bottom = m_CenterY + (m_MaxHauteur/2) - m_EdgeBottom;
254 m_Left = m_CenterX - (m_MaxLargeur/2) + m_EdgeLeft;
255 m_Right = m_CenterX + (m_MaxLargeur/2) - m_EdgeRight;
259 void wxChart::SetChartBoundsLegend()
261 m_TopLegend = m_CenterY - (m_MaxHauteur/2) + m_EdgeTopLegend;
262 m_BottomLegend = m_CenterY + (m_MaxHauteur/2) - m_EdgeBottomLegend;
263 m_LeftLegend = m_CenterX - (m_MaxLargeur/2) + m_EdgeLeftLegend;
264 m_RightLegend = m_CenterX + (m_MaxLargeur/2) - m_EdgeRightLegend;
268 void wxChart::SetCadreLegend(int nbr, int *bottom)
270 int val=GetEdgeBottom();
271 div_t result = div(nbr, 2);
274 val+= (nbr * 10) + 5;
276 val+= (( nbr + 1 ) * 10) + 5;
280 SetEdgeTopLegend(m_CenterY + (m_MaxHauteur/2) - val + 33);
281 SetEdgeBottomLegend(8);
283 int l_left = GetEdgeLeft();
284 int l_right = GetEdgeRight();
286 // more small for only 1 line
289 l_left+=m_CenterX - (m_MaxLargeur/3);
290 l_right+=m_CenterX - (m_MaxLargeur/3);
293 SetEdgeLeftLegend(l_left);
294 SetEdgeRightLegend(l_right);
299 void wxChart::SetShowPer(bool per)
306 void wxChart::SetMaxValue(double max)
315 double wxChart::MaxValue()
317 double data, val = 1.00;
318 int maxdata = GetNumDataSet()-1;
319 int maxitem = GetNumItem();
321 // Exclure Stenosis for calcul MaxValue
322 for(int a=0; a < maxdata; a++)
324 if (GetShowDataSet(a))
326 for(int j=0; j<=maxitem; j++)
328 if ( IsEmpty(a,j) == false )
330 data = GetDataY(a,j);
342 double wxChart::MinCol(double min)
344 double retour = 0.00;
345 int maxdata = GetNumDataSet()-1;
347 // Exclure Stenosis for calcul MaxValue
348 for(int a=0; a < maxdata; a++)
350 if (GetShowDataSet(a))
362 double wxChart::MaxCol(double max)
364 double retour = 1.00;
365 int maxdata = GetNumDataSet()-1;
367 // Exclure Stenosis for calcul MaxValue
368 for(int a=0; a < maxdata; a++)
370 if (GetShowDataSet(a))
383 void wxChart::SetStepSizeX(double stepX)
388 void wxChart::SetStepSizeY(double stepY)
394 void wxChart::SetStepSizePer(double stepPer)
396 m_StepSizePer = stepPer;
400 void wxChart::SetCenterChart(int x, int y)
406 void wxChart::SetMaxWidthHeight(int x,int y)
413 void wxChart::SetMinX(double MinX)
419 void wxChart::SetMaxX(double MaxX)
426 void wxChart::SetEdgeTop(int top)
431 void wxChart::SetEdgeBottom(int bottom)
433 m_EdgeBottom = bottom;
436 void wxChart::SetEdgeLeft(int left)
441 void wxChart::SetEdgeRight(int right)
447 void wxChart::SetEdgeTopLegend(int top)
449 m_EdgeTopLegend = top;
452 void wxChart::SetEdgeBottomLegend(int bottom)
454 m_EdgeBottomLegend = bottom;
457 void wxChart::SetEdgeLeftLegend(int left)
459 m_EdgeLeftLegend = left;
463 void wxChart::SetEdgeRightLegend(int right)
465 m_EdgeRightLegend = right;
470 void wxChart::SetNumDataSet(int num)
475 void wxChart::SetNumItem(int num)
481 int wxChart::GetShow()
485 for(int i=0; i < m_NumDataSet ; i++)
487 if (GetShowDataSet(i))
494 void wxChart::InitDataSet()
499 for(int i=0; i<MAX_DATASET ; i++)
500 m_dataSetArray[i]=NULL;
503 wxColour *BlueColour = new wxColour(0,0,255);
504 wxColour *GreyColour = new wxColour(192,192,192);
505 wxColour *YellowColour = new wxColour(255,255,0);
506 wxColour *VioletColour = new wxColour(255,0,255);
507 wxColour *CyanColour = new wxColour(0,255,255);
510 // Create All DataSet
511 // Per default : Show(false)
512 m_dataSetArray[wxArea] =
513 new wxDataSet(wxRED_PEN, wxRED_BRUSH, (wxString*)"Area");
515 m_dataSetArray[wxPerimeter] =
516 new wxDataSet(new wxPen(*BlueColour, 1, wxSOLID),
517 new wxBrush(*BlueColour, wxSOLID),
518 (wxString*)"Perimeter");
520 m_dataSetArray[wxDiameterArea] =
521 new wxDataSet(new wxPen(*GreyColour, 1, wxSOLID),
522 new wxBrush(*GreyColour, wxSOLID),
523 (wxString*)"Diameter from area");
525 m_dataSetArray[wxDiameterPerimeter] =
526 new wxDataSet(new wxPen(*YellowColour, 1, wxSOLID),
527 new wxBrush(*YellowColour, wxSOLID),
528 (wxString*)"Diameter from perimeter");
530 m_dataSetArray[wxMinimumDiameter] =
531 new wxDataSet(new wxPen(*VioletColour, 1, wxSOLID),
532 new wxBrush(*VioletColour, wxSOLID),
533 (wxString*)"Minimum diameter");
535 m_dataSetArray[wxMaximumDiameter] =
536 new wxDataSet(new wxPen(*CyanColour, 1, wxSOLID),
537 new wxBrush(*CyanColour, wxSOLID),
538 (wxString*)"Maximum diameter");
540 m_dataSetArray[wxAverageDiameter] =
541 new wxDataSet(wxBLACK_PEN, wxBLACK_BRUSH, (wxString*)"Average diameter");
543 m_dataSetArray[wxStenosis] =
544 new wxDataSet(wxGREEN_PEN, wxGREEN_BRUSH, (wxString*)"Stenosis");
550 //---------------------------------------------------------------------
551 void wxChart::OnPaint(wxPaintEvent& event)
559 void wxChart::Draw(wxDC& dc)
564 //----------------------------------------------------------------------------
570 //----------------------------------------------------------------------------
571 // Font : one for all chart
572 dc.SetFont(*(new wxFont(1, wxDEFAULT, wxNORMAL, wxLIGHT)));
574 //----------------------------------------------------------------------------
576 wxSize size = GetClientSize();
577 SetMaxWidthHeight(size.GetWidth(), size.GetHeight());
578 SetCenterChart((GetLargeur()/2), (GetHauteur()/2));
581 //-----------------------------------------------------------------------------
583 ShowDataSet(true,wxArea);
584 ShowDataSet(true,wxPerimeter);
585 ShowDataSet(true,wxDiameterArea);
586 ShowDataSet(false,wxDiameterPerimeter);
587 ShowDataSet(false,wxMinimumDiameter);
588 ShowDataSet(false,wxMaximumDiameter);
589 ShowDataSet(false,wxAverageDiameter);
590 ShowDataSet(false,wxStenosis);
598 ShowDataSet(true,wxStenosis);
602 //--------------------------------------------------------------------
607 SetCadreLegend(nbr, &m_EdgeBottom);
608 SetChartBoundsLegend();
612 //-------------------------------------------------------------------
613 // Valeur Min et Max des abscisses
616 SetInfX(st_difference(m_MinX,10,false));
617 SetSupX(st_difference(m_MaxX,10,true));
619 //------------------------------------------------------------------
623 SetData(wxStenosis, 0, 0, -45);
624 SetData(wxStenosis, 1, 0.4, 0);
625 SetData(wxStenosis, 2, 0.6, -15);
626 SetData(wxStenosis, 3, 0.8, 0);
627 SetData(wxStenosis, 4, 0.9, 100);
628 SetData(wxStenosis, 5, 1, 0);
631 SetData(wxArea,0, 0, 0.8);
632 SetData(wxArea,1, 0.2, 0.6);
633 SetData(wxArea,2, 0.3, 0.8);
634 SetData(wxArea,3, 0.4, 1);
635 SetData(wxArea,4, 0.8, 0.4);
636 SetData(wxArea,5, 1, 0.2);
638 //-----------------------------------------------------------------
639 // Valeur Max du chart
640 SetMaxValue(MaxValue());
641 SetSupY(st_difference(m_MaxValue, 10, true));
643 //-------------------------------------------------------------------------------
645 SetIncAxisX((m_MaxX + m_SupX - (m_MinX - m_InfX)) / (double)MINOR_STEP,
646 (m_MaxX + m_SupX - (m_MinX - m_InfX)) / (double)MAJOR_STEP);
647 SetIncAxisY((m_MaxValue + m_SupY) / (double)MINOR_STEP,
648 (m_MaxValue + m_SupY) / (double)MAJOR_STEP);
650 SetStepSizeX(( m_MaxLargeur - (m_EdgeLeft + m_EdgeRight + m_SupX + m_InfX)) /
652 SetStepSizeY(( m_MaxHauteur - (m_EdgeBottom + m_EdgeTop + m_SupY )) /
654 SetStepSizePer(( m_MaxHauteur - (m_EdgeBottom + m_EdgeTop)) /
658 //-----------------------------------------------------------------------------
660 //---------------------------------------------------------------------------
667 //-----------------------------------------------------------------------------
669 //---------------------------------------------------------------------------
670 dc.DestroyClippingRegion();
671 dc.SetClippingRegion(m_Left , m_Top ,
672 GetLargeur() - (m_EdgeRight + m_EdgeLeft ),
673 GetHauteur() - (m_EdgeTop + m_EdgeBottom ));
675 //---------------------------------------------------------------------------
677 //---------------------------------------------------------------------------
678 int maxdataset = GetNumDataSet();
679 for(int a=0; a < maxdataset; a++)
681 if(m_dataSetArray[a] && m_dataSetArray[a]->GetShow())
683 dataBrush = m_dataSetArray[a]->GetDataStyle();
684 dataPen = m_dataSetArray[a]->GetLineStyle();
685 dc.SetBrush(*dataBrush);
691 //---------------------------------------
693 dc.DestroyClippingRegion();
699 void wxChart::DrawAxe(wxDC& dc)
706 double minorIncStepY= m_MinorIncY * m_StepSizeY;
707 double majorIncStepY= m_MajorIncY * m_StepSizeY;
709 double minorIncStepX= m_MinorIncX * m_StepSizeX;
710 double majorIncStepX= m_MajorIncX * m_StepSizeX;
712 dc.SetPen(*wxBLACK_PEN);
713 dc.SetBrush(*wxBLACK_BRUSH);
716 dc.DrawLine(m_Left, m_Bottom+(7*MARGE/4), m_Right, m_Bottom+(7*MARGE/4));
718 dc.DrawLine(m_Left-(7*MARGE/4), m_Bottom, m_Left-(7*MARGE/4), m_Top);
721 // Major Tick Marks with values
723 for(x=m_Left,y=m_Bottom; y >= m_Top; y-=majorIncStepY, val+=m_MajorIncY)
725 dc.DrawLine(m_Left-7-(7*MARGE/4),y,m_Left-(7*MARGE/4),y);
726 sprintf(text,"%g", val);
727 dc.GetTextExtent(text,&widthx,&heighty);
728 dc.DrawText(text,m_Left-10-widthx-(7*MARGE/4),y-(heighty/2));
733 dc.DrawLine(m_Left-7-(7*MARGE/4),m_Top,m_Left-(7*MARGE/4),m_Top);
734 sprintf(text,"%g", val);
735 dc.GetTextExtent(text,&widthx,&heighty);
736 dc.DrawText(text,m_Left-10-widthx-(7*MARGE/4),m_Top-(heighty/2));
740 for(x=m_Left,y=m_Bottom; y >= m_Top; y-=minorIncStepY)
742 dc.DrawLine(m_Left-3-(7*MARGE/4),y,m_Left-(7*MARGE/4),y);
746 // Major Tick Marks with values
747 supx = st_decalage(m_MajorIncX, m_MinX) * m_StepSizeX;
748 val = st_origine(m_MajorIncX, m_MinX);
749 for(y=m_Bottom,x=m_Left + supx; x <= m_Right; x+=majorIncStepX, val+=m_MajorIncX)
751 dc.DrawLine(x,m_Bottom+7+(7*MARGE/4),x,m_Bottom+(7*MARGE/4));
752 sprintf(text,"%g", val);
753 dc.GetTextExtent(text,&widthx,&heighty);
754 dc.DrawText(text,x-(widthx/2),y+3+heighty);
759 dc.DrawLine(m_Right,m_Bottom+7+(7*MARGE/4),m_Right,m_Bottom+(7*MARGE/4));
760 sprintf(text,"%g", val);
761 dc.GetTextExtent(text,&widthx,&heighty);
762 dc.DrawText(text,m_Right-(widthx/2),m_Right+3+heighty);
765 supx = st_decalage(m_MinorIncX, m_MinX) * m_StepSizeX;
767 for(y=m_Bottom,x=m_Left + supx; x <= m_Right; x+=minorIncStepX)
769 dc.DrawLine(x,m_Bottom+3+(7*MARGE/4),x,m_Bottom+(7*MARGE/4));
774 void wxChart::DrawAxePer(wxDC& dc)
781 double minorIncStepPer= MINOR_PER * m_StepSizePer;
782 double majorIncStepPer= MAJOR_PER * m_StepSizePer;
784 dc.SetPen(*wxBLACK_PEN);
785 dc.SetBrush(*wxBLACK_BRUSH);
788 dc.DrawLine(m_Right+(7*MARGE/4), m_Bottom, m_Right+(7*MARGE/4), m_Top);
790 // Major Tick Marks with values
792 for(x=m_Right,y=m_Bottom; y >= m_Top; y-=majorIncStepPer, val+=MAJOR_PER)
794 dc.DrawLine(m_Right+(7*MARGE/4),y,m_Right+7+(7*MARGE/4),y);
795 sprintf(text,"%g",(val-(MAX_PER/2)));
796 dc.GetTextExtent(text,&widthx,&heighty);
797 dc.DrawText(text,m_Right+10+(7*MARGE/4),y-(heighty/2));
799 dc.DrawLine(m_Right+(7*MARGE/4),m_Top,m_Right+7+(7*MARGE/4),m_Top);
800 sprintf(text,"%g",(val-(MAX_PER/2)));
801 dc.GetTextExtent(text,&widthx,&heighty);
802 dc.DrawText(text,m_Right+10+(7*MARGE/4),m_Top-(heighty/2));
805 for(x=m_Right,y=m_Bottom; y >= m_Top; y-=minorIncStepPer)
807 dc.DrawLine(m_Right+(7*MARGE/4),y,m_Right+3+(7*MARGE/4),y);
813 void wxChart::DrawGrille(wxDC& dc)
817 double minorIncStepY = m_MinorIncY * m_StepSizeY;
818 double minorIncStepX = m_MinorIncX * m_StepSizeX;
820 dc.SetBrush(*wxLIGHT_GREY_BRUSH);
823 wxPen *Pen = new wxPen(*wxLIGHT_GREY, 1, wxDOT);
826 // quadrillage en point
828 for(x=m_Left,y=m_Bottom; y >= m_Top; y-=minorIncStepY)
829 dc.DrawLine(m_Left-MARGE,y,m_Right+MARGE,y);
831 dc.DrawLine(m_Left-MARGE,m_Top,m_Right+MARGE,m_Top);
834 val = st_decalage(m_MinorIncX, m_MinX) * m_StepSizeX;
835 for(y=m_Bottom, x=m_Left + val ; x <= m_Right; x+=minorIncStepX)
836 dc.DrawLine(x,m_Bottom+MARGE,x,m_Top-MARGE);
838 dc.DrawLine(m_Right,m_Bottom+MARGE,m_Right,m_Top-MARGE);
841 Pen->SetStyle(wxSOLID);
843 dc.DrawLine(m_Left-MARGE, m_Top-MARGE, m_Right+MARGE, m_Top-MARGE);
844 dc.DrawLine(m_Right+MARGE, m_Top-MARGE, m_Right+MARGE, m_Bottom+MARGE);
845 dc.DrawLine(m_Right+MARGE, m_Bottom+MARGE, m_Left-MARGE, m_Bottom+MARGE);
846 dc.DrawLine(m_Left-MARGE, m_Bottom+MARGE, m_Left-MARGE, m_Top-MARGE);
851 void wxChart::DrawLegend(wxDC& dc, int nbre)
857 int widthx, heighty, l_posx, l_posy;
859 int haut_ligne, compt = 0;
860 int l_haut = m_BottomLegend - m_TopLegend;
861 int l_larg = m_RightLegend - m_LeftLegend;
862 div_t result = div(nbre,2);
864 int l_debut = 30, l_trait = 15, l_space = 10;
867 haut_ligne = l_haut / result.quot;
869 haut_ligne = l_haut / (result.quot+1);
872 dc.SetPen(*wxBLACK_PEN);
873 dc.SetBrush(*wxBLACK_BRUSH);
874 dc.DrawLine(m_LeftLegend, m_TopLegend, m_RightLegend, m_TopLegend);
875 dc.DrawLine(m_RightLegend, m_TopLegend, m_RightLegend, m_BottomLegend);
876 dc.DrawLine(m_RightLegend, m_BottomLegend, m_LeftLegend, m_BottomLegend);
877 dc.DrawLine(m_LeftLegend, m_BottomLegend, m_LeftLegend, m_TopLegend);
880 int maxdataset = GetNumDataSet();
881 for (int a=0; a < maxdataset; a++)
883 if (m_dataSetArray[a] && m_dataSetArray[a]->GetShow())
887 string = m_dataSetArray[a]->GetText();
888 sprintf(text,"%s",string);
889 dc.GetTextExtent(text,&widthx,&heighty);
891 resulta = div(compt, 2);
892 l_posx = m_LeftLegend;
893 l_posy = m_TopLegend;
894 if (resulta.rem == 0)
897 l_posy+= (haut_ligne * resulta.quot);
900 l_posy+= (haut_ligne * (resulta.quot+1));
902 l_posy-= (haut_ligne/2);
906 l_posx = m_LeftLegend + ((l_larg - l_trait - l_space - widthx)/2) - l_debut;
909 dataBrush = m_dataSetArray[a]->GetDataStyle();
910 dataPen = m_dataSetArray[a]->GetLineStyle();
911 dataPen->SetWidth(2);
912 dc.SetBrush(*dataBrush);
914 dc.DrawLine(l_posx + l_debut, l_posy, l_posx + l_debut + 15, l_posy);
915 dataPen->SetWidth(1);
917 dc.SetFont(*(new wxFont(1, wxDEFAULT, wxNORMAL, wxBOLD)));
918 dc.SetPen(*wxBLACK_PEN);
919 dc.SetBrush(*wxBLACK_BRUSH);
920 dc.DrawText(text,l_posx + l_debut + l_trait + l_space ,l_posy - (heighty/2));
921 dc.SetFont(*(new wxFont(1, wxDEFAULT, wxNORMAL, wxLIGHT)));
928 void wxChart::DrawLine(wxDC &dc, int a)
932 double mid = m_Bottom - ((m_Bottom-m_Top)/2);
933 int maxitem = GetNumItem();
938 for(int j=0; j < maxitem; j++)
940 if ( IsEmpty(a,j) == false )
943 xsuiv = m_Left + ((GetDataX(a,j) - m_MinX ) * m_StepSizeX);
945 if ( a == wxStenosis)
946 // Axe Per for Stenosis
947 ysuiv = mid - (val * m_StepSizePer);
950 ysuiv = m_Bottom - (val * m_StepSizeY);
953 dc.DrawLine(xprec, yprec, xsuiv, ysuiv);
964 //-----------------------------------------------------------------
965 void wxChart::OnLeftClick(wxDC &dc, double x, double y, int keys)
970 void wxChart::OnRightClick(wxDC &dc, double x, double y, int keys)
977 //--------------------------------------------------------------------
978 void wxChart::InitData()
981 for(int a=0; a<MAX_DATASET; a++)
983 for(int j=0; j<MAX_ITEM; j++)
985 m_table[a][j].x=0.00;
986 m_table[a][j].y=0.00;
987 m_table[a][j].empty = true;
992 bool wxChart::IsEmpty(int a, int j)
994 return m_table[a][j].empty;
998 double wxChart::GetDataX(int a, int j)
1001 return m_table[a][j].x;
1004 double wxChart::GetDataY(int a, int j)
1007 return m_table[a][j].y;
1011 void wxChart::SetData(int a, int j, double x, double y)
1013 m_table[a][j].x = x;
1014 m_table[a][j].y = y;
1015 m_table[a][j].empty = false;
1019 void wxChart::ShowDataSet(bool show,int dataset)
1021 if(m_dataSetArray[dataset])
1022 m_dataSetArray[dataset]->Show(show);
1025 bool wxChart::GetShowDataSet(int dataset)
1028 if(m_dataSetArray[dataset])
1029 return m_dataSetArray[dataset]->GetShow();