From a6c8b5701d40f2c970530f2efb027751cd18e3db Mon Sep 17 00:00:00 2001 From: koldo Date: Sat, 23 Oct 2010 20:30:11 +0000 Subject: [PATCH] .Scatter: Now mouse shape changes when scrolling git-svn-id: svn://ultimatepp.org/upp/trunk@2814 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- bazaar/Scatter/Scatter.cpp | 3452 ++++++++++++++++++------------------ 1 file changed, 1726 insertions(+), 1726 deletions(-) diff --git a/bazaar/Scatter/Scatter.cpp b/bazaar/Scatter/Scatter.cpp index 99e239722..394f24637 100644 --- a/bazaar/Scatter/Scatter.cpp +++ b/bazaar/Scatter/Scatter.cpp @@ -1,1726 +1,1726 @@ -#include "Scatter.h" - -#define IMAGECLASS ChartImg -#define IMAGEFILE -#include - -Scatter::MouseBehaviour defaultMouse[] = { - {false, false, false, true , false, 0, false, Scatter::SHOW_INFO}, - {false, false, false, false, true , 0, false, Scatter::SCROLL}, - {false, false, false, false, false, 1, false, Scatter::ZOOM_H_RED}, - {false, false, false, false, false, 1, false, Scatter::ZOOM_V_RED}, - {false, false, false, false, false,-1, false, Scatter::ZOOM_H_ENL}, - {false, false, false, false, false,-1, false, Scatter::ZOOM_V_ENL}, - {false, false, false, false, false, 0, false, Scatter::NO_ACTION}}; - - -Scatter& Scatter::SetColor(const class::Color& _color) -{ - graphColor=_color; - return *this; -} - -Scatter& Scatter::SetTitle(const String& _title) -{ - title=_title; - return *this; -} -Scatter& Scatter::SetTitleFont(const Font& fontTitle) -{ - titleFont=fontTitle; - return *this; -} -Scatter& Scatter::SetTitleColor(const class::Color& colorTitle) -{ - titleColor=colorTitle; - return *this; -} -void Scatter::SetLabels(const WString& _xLabel, const WString& _yLabel, const WString& _yLabel2) -{ - xLabel=_xLabel; - yLabel=_yLabel; - yLabel2=_yLabel2; -} -Scatter& Scatter::SetLabelX(const WString& _xLabel) -{ - xLabel=_xLabel; - return *this; -} -Scatter& Scatter::SetLabelY(const WString& _yLabel) -{ - yLabel=_yLabel; - return *this; -} -Scatter& Scatter::SetLabelY2(const WString& _yLabel) -{ - yLabel2=_yLabel; - return *this; -} -Scatter& Scatter::SetLabelsFont(const Font& fontLabels) -{ - labelsFont=fontLabels; - return *this; -} -Scatter& Scatter::SetLabelsColor(const class::Color& colorLabels) -{ - labelsColor=colorLabels; - return *this; -} -Scatter& Scatter::SetPlotAreaPoz(const int& poz_x, const int& poz_y) -{ - px=poz_x; - py=poz_y; - return *this; -} -Scatter& Scatter::H_Border(const int& poz_x) -{ - if(poz_x>=0) px=poz_x; - return *this; -} -Scatter& Scatter::V_Border(const int& poz_y) -{ - if(poz_y>=0) py=poz_y; - return *this; -} - -Scatter& Scatter::SetPlotAreaColor(const class::Color& p_a_color) -{ - plotAreaColor=p_a_color; - return *this; -} -Scatter& Scatter::SetAxisColor(const class::Color& axis_color) -{ - axisColor=axis_color; - return *this; -} -Scatter& Scatter::SetAxisWidth(const int& axis_width) -{ - axisWidth=axis_width; - return *this; -} -Scatter& Scatter::SetGridColor(const class::Color& grid_color) -{ - gridColor=grid_color; - return *this; -} -Scatter& Scatter::SetGridWidth(const int& grid_width) -{ - gridWidth=grid_width; - return *this; -} -Scatter& Scatter::ShowHGrid(const bool& show) -{ - drawHGrid=show; - return *this; -} -Scatter& Scatter::ShowVGrid(const bool& show) -{ - drawVGrid=show; - return *this; -} -Scatter& Scatter::ShowLegend(const bool& show) -{ - showLegend=show; - return *this; -} -Scatter& Scatter::SetLegendWeight(const int& weight) -{ - legendWeight=weight; - return *this; -} -Scatter& Scatter::SetAntialiasing(const bool& aa) -{ - antialiasing=aa; - return *this; -} -Scatter &Scatter::SetDrawXReticle(bool set) -{ - drawXReticle = set; - return *this; -} -Scatter &Scatter::SetDrawYReticle(bool set) -{ - drawYReticle = set; - return *this; -} -Scatter &Scatter::SetDrawY2Reticle(bool set) -{ - drawY2Reticle = set; - return *this; -} -void Scatter::DrawLegend(Draw& w,const int& scale) const -{ - Vector L; - L.Append(vLegend); - L.Append(vFLegend); - Vector Thick; - Thick.Append(vPThickness); - Thick.Append(vFThickness); - Vector LC; - LC.Append(vPColors); - LC.Append(vFColors); - Vector LW; - LW.Append(vPWidth); - VectorVJ; - VJ.Append(vJoin); - Vector MS; - MS.Append(vMarkStyles); - Vector MC; - MC.Append(vMarkColors); - Vector Patt; - Patt.Append(vPPattern); - Patt.Append(vFPattern); - - int NMR=fround((GetSize().cx-2*px)/legendWeight);//max number of labels per row - if (NMR>0) - { - int N=L.GetCount();//number of labels - int Nc;//number of complete rows - int LCR;//number of labels on complete row - int R;//number of remaining labels on incomplete row - if(NMR>N) {Nc=0; LCR=0; R=N;} - else if (NMR==N) {Nc=1; LCR=N; R=0;} - else {Nc=N/NMR; LCR=NMR; R=N%NMR;} - for(int j=0;j<=Nc;j++) - { - int start=N-(j+1)*LCR; - int end=N-j*LCR; - if (j==Nc) {start=0; end=R;} - for(int i=start;i vp; - vp << Point(scale*(i-start)*legendWeight, scale*(4-12*(j+1))) << - Point(scale*(i-start)*legendWeight+scale*23, scale*(4-12*(j+1))); - if (VJ.At(i)) - DrawPolylineX(w, vp, scale*Thick.At(i)/6, LC.At(i), Patt.At(i), scale); - Point p(scale*((i-start)*legendWeight+7),scale*(4-12*(j+1))/*+scale*Thick.At(i)/12*/); - if (LW.At(i,0) > 1) - DrawMark(MS.At(i),w,scale,p,LW.At(i,0),MC.At(i)); - Font scaledFont; - scaledFont.Height(scale*StdFont().GetHeight()); - w.DrawText(scale*(i-start)*legendWeight+scale*25, - scale*(-2-12*(j+1)), - L.At(i), - scaledFont,LC.At(i)); - } - } - } -} - -void Scatter::AdjustMinUnitX() -{ - while (xMinUnit < 0) - xMinUnit += xMajorUnit; - while (xMinUnit > xMajorUnit) - xMinUnit -= xMajorUnit; -} -void Scatter::AdjustMinUnitY() -{ - while (yMinUnit < 0) - yMinUnit += yMajorUnit; - while (yMinUnit > yMajorUnit) - yMinUnit -= yMajorUnit; -} -void Scatter::AdjustMinUnitY2() -{ - if (yMajorUnit2 > 0) { - while (yMinUnit2 < 0) - yMinUnit2 += yMajorUnit2; - while (yMinUnit2 > yMajorUnit2) - yMinUnit2 -= yMajorUnit2; - } -} -Scatter &Scatter::SetRange(double rx, double ry, double ry2) -{ - xRange=rx; - yRange=ry; - yRange2=ry2; - xMajorUnit=xRange/10; - AdjustMinUnitX(); - yMajorUnit=yRange/10; - AdjustMinUnitY(); - yMajorUnit2=yRange2/10; - AdjustMinUnitY2(); - WhenSetRange(); - return *this; -} -Scatter &Scatter::SetMajorUnits(double ux, double uy) -{ - //if (ux > xRange) throw (Exc(t_("Invalid X major units!"))); - //if (uy > yRange) throw (Exc(t_("Invalid Y major units!"))); - xMajorUnit=ux; - yMajorUnit=uy; - yMajorUnit2=yRange2*yMajorUnit/yRange; - AdjustMinUnitX(); - AdjustMinUnitY(); - AdjustMinUnitY2(); - return *this; -} -Scatter &Scatter::SetMinUnits(double ux, double uy) -{ - xMinUnit=ux; - yMinUnit=uy; - yMinUnit2=yRange2*yMinUnit/yRange; - AdjustMinUnitX(); - AdjustMinUnitY(); - AdjustMinUnitY2(); - return *this; -} -Scatter &Scatter::SetXYMin(double xmin, double ymin, double ymin2) -{ - xMin=xmin; - yMin=ymin; - yMin2=ymin2; - WhenSetXYMin(); - return *this; -} - -void Scatter::FitToData(bool Y) { - double minx, maxx, miny, miny2, maxy, maxy2; - minx = miny = miny2 = -DOUBLE_NULL; - maxx = maxy = maxy2 = DOUBLE_NULL; - - for (int j=0; j maxx) - maxx = vPointsData[j][i].x; - } - } - for (int j=0; j maxy) - maxy = vPointsData[j][i].y; - } else { - if (vPointsData[j][i].y < miny2) - miny2 = vPointsData[j][i].y; - if (vPointsData[j][i].y > maxy2) - maxy2 = vPointsData[j][i].y; - } - } - } - for (int j=0; j & points,const String& legend,const bool& join, const class::Color& pcolor, const int& width, const int& thickness) -{ - vPointsData.AddPick(points); - vJoin.Add(join); - vSmooth.Add(false); - vPColors.Add(pcolor); - vPWidth.Add(width); - vPThickness.Add(thickness); - vLegend.Add(legend); - vMarkColors.Add(pcolor); - if (width <= 1) - vShowMark.Add(false); - else - vShowMark.Add(true); - vMarkStyles.Add(CIRCLE); - vPPrimaryY.Add(true); - vPSequential.Add(sequentialXAll); - vPPattern.Add(LINE_SOLID); - - Refresh(); - return *this; -} - -Scatter &Scatter::SetPattern(const String pattern) -{ - vPPattern[vPPattern.GetCount()-1] = pattern; - return *this; -} - -void Scatter::AddPoint(const int& j, const XY & point, const bool& refresh) -{ - if(IsValid(j)) - { - vPointsData[j].Add(point); - if(refresh) Refresh(); - } -} -void Scatter::InsertPoint(const int& j, const int& i, const XY & point) -{ - if(IsValid(j)) - { - if(i>=0 && vPointsData[j].GetCount()>=i) - { - vPointsData[j].Insert(i,point); - Refresh(); - } - } -} -void Scatter::RemovePoint(const int& j, const int& i) -{ - if(IsValid(j)) - { - if(i>=0 && vPointsData[j].GetCount()>i) - { - vPointsData[j].Remove(i); - Refresh(); - } - } -} -void Scatter::SetData(const int& j, const int& i, const XY & point) -{ - if(IsValid(j)) - { - if(i>=0 && vPointsData[j].GetCount()>i) - { - vPointsData[j][i]=point; - Refresh(); - } - } -} - -void Scatter::SetData(const int& j, Vector & points) -{ - if(IsValid(j)) - { - vPointsData[j]<<=points; - Refresh(); - } -} -void Scatter::SetDataColor(const int& j, const class::Color& pcolor) -{ - if(IsValid(j)) - { - vPColors[j]=pcolor; - Refresh(); - } -} -void Scatter::SetFunctColor(const int& j, const class::Color& fcolor) -{ - if(IsValid(j)) - { - vFColors[j]=fcolor; - Refresh(); - } -} -Color Scatter::GetDataColor(const int& j) const -{ - if(IsValid(j)) - { - return vPColors[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -Color Scatter::GetFunctColor(const int& j) const -{ - if(IsValid(j)) - { - return vFColors[j]; - } - throw (Exc(t_("Invalid function index!"))); -} - -void Scatter::SetDataThickness(const int& j, const int& thick_dots) -{ - if(IsValid(j)) - { - vPThickness[j]=thick_dots; - Refresh(); - } -} - -void Scatter::SetFunctThickness(const int& j, const int& thick_dots) -{ - if(IsValid(j)) - { - vFThickness[j]=thick_dots; - Refresh(); - } -} -int Scatter::GetDataThickness(const int& j) const -{ - if(IsValid(j)) - { - return vPThickness[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -int Scatter::GetFunctThickness(const int& j) const -{ - if(IsValid(j)) - { - return vFThickness[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -void Scatter::SetMarkWidth(const int& j, const int& width_dots) -{ - if(IsValid(j)) - { - vPWidth[j]=width_dots; - Refresh(); - } -} - -int Scatter::GetMarkWidth(const int& j) const -{ - if(IsValid(j)) - { - return vPWidth[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -void Scatter::SetMarkStyle(const int& j, MarkStyle noStyle) -{ - if(IsValid(j)) - { - vMarkStyles[j]=noStyle; - Refresh(); - } -} - -int Scatter::GetMarkStyle(const int& j) const -{ - if(IsValid(j)) - { - return vMarkStyles[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -void Scatter::SetMarkColor(const int& j, const ::Color& mcolor) -{ - if(IsValid(j)) - { - vMarkColors[j]=mcolor; - Refresh(); - } -} - -Color Scatter::GetMarkColor(const int& j) const -{ - if(IsValid(j)) - { - return vMarkColors[j]; - } - throw (Exc(t_("Invalid series index!"))); -} - -void Scatter::SetShowMark(const int& j, const bool& show) -{ - if(IsValid(j)) - { - vShowMark[j]=show; - Refresh(); - } -} - -bool Scatter::IsMarkShow(const int& j) const throw (Exc) -{ - if(!IsValid(j)) throw (Exc(t_("Invalid series index!"))); - return vShowMark[j]; -} - -void Scatter::SetJoin(const int& j, const bool& join) -{ - if(IsValid(j)) - { - vJoin[j]=join; - Refresh(); - } -} - -bool Scatter::IsJoined(const int& j) const throw (Exc) -{ - if(!IsValid(j)) throw (Exc(t_("Invalid series index!"))); - - return vJoin[j]; -} - -void Scatter::SetSmooth(const int& j, const bool& smooth) -{ - if(IsValid(j)) - { - vSmooth[j]=smooth; - Refresh(); - } -} - -bool Scatter::IsSmooth(const int& j) const throw (Exc) -{ - if(!IsValid(j)) throw (Exc(t_("Invalid series index!"))); - - return vSmooth[j]; -} - -void Scatter::SetDataPrimaryY(const int& j, const bool& primary) -{ - if(IsValid(j)) - { - vPPrimaryY[j]=primary; - Refresh(); - } -} - -Scatter &Scatter::SetDataPrimaryY(const bool& primary) -{ - SetDataPrimaryY(vPPrimaryY.GetCount()-1, primary); - return *this; -} - -bool Scatter::IsDataPrimaryY(const int& j) const throw (Exc) -{ - if(!IsValid(j)) throw (Exc(t_("Invalid series index!"))); - - return vPPrimaryY[j]; -} - -void Scatter::SetSequentialX(const int& j, const bool& sequential) -{ - if(IsValid(j)) - { - vPSequential[j]=sequential; - Refresh(); - } -} - -Scatter &Scatter::SetSequentialX(const bool& sequential) -{ - SetSequentialX(vPSequential.GetCount()-1, sequential); - return *this; -} - -Scatter &Scatter::SetSequentialXAll(const bool& sequential) -{ - for (int i = 0; i < vPSequential.GetCount(); ++i) - SetSequentialX(i, sequential); - sequentialXAll = sequential; - return *this; -} - -void Scatter::SetFunctPrimaryY(const int& j, const bool& primary) -{ - if(IsValid(j)) - { - vFPrimaryY[j]=primary; - Refresh(); - } -} - -Scatter &Scatter::SetFunctPrimaryY(const bool& primary) -{ - SetFunctPrimaryY(vFPrimaryY.GetCount()-1, primary); - return *this; -} - -bool Scatter::IsFunctPrimaryY(const int& j) const throw (Exc) -{ - if(!IsValid(j)) throw (Exc(t_("Invalid series index!"))); - - return vFPrimaryY[j]; -} - -void Scatter::RemoveSeries(const int& j) -{ - if (IsValid(j)) - { - vPointsData.Remove(j); - vJoin.Remove(j); - vSmooth.Remove(j); - vPColors.Remove(j); - vPWidth.Remove(j); - vPThickness.Remove(j); - vLegend.Remove(j); - vMarkColors.Remove(j); - vShowMark.Remove(j); - vMarkStyles.Remove(j); - vPPrimaryY.Remove(j); - vPPattern.Remove(j); - vPSequential.Remove(j); - - Refresh(); - } -} - -void Scatter::RemoveAllSeries() -{ - vPointsData.Clear(); - vJoin.Clear(); - vSmooth.Clear(); - vPColors.Clear(); - vPWidth.Clear(); - vPThickness.Clear(); - vLegend.Clear(); - vMarkColors.Clear(); - vShowMark.Clear(); - vMarkStyles.Clear(); - vPPrimaryY.Clear(); - vPSequential.Clear(); - vPPattern.Clear(); - - Refresh(); -} - - -void Scatter::PlotFunction(double (*f)(double), const String& legend, const class::Color& fcolor, const int& weight) -{ - Vector series; - vFunctionData.AddPick(series); - - vAdress.Add(f); - - vFColors.Add(fcolor); - vFThickness.Add(weight); - vFLegend.Add(legend); - vFPrimaryY.Add(true); - vFPattern.Add(LINE_SOLID); - Refresh(); -} -void Scatter::PlotParaFunction(XY (*pf)(double), const String& legend, const class::Color& fcolor, const int& weight,const int& Np) -{ - double t;//t must be choosed between [0,1] - Vector series; - for (int i=0; i<=Np;i++) - { - t=(double)i/Np; - series<j) - { - if(vFunctionData[j].IsEmpty()) - { - int nf=-1; - for(int i=0; i<=j; i++) - { - if (vFunctionData[i].IsEmpty()) nf++; - } - vAdress.Remove(nf); - } - - vFunctionData.Remove(j); - vFColors.Remove(j); - vFThickness.Remove(j); - vFLegend.Remove(j); - vFPrimaryY.Remove(j); - vFPattern.Remove(j); - - Refresh(); - } -} - -void Scatter::RemoveAllFSeries() -{ - vAdress.Clear(); - vFunctionData.Clear(); - vFColors.Clear(); - vFThickness.Clear(); - vFLegend.Clear(); - vFPrimaryY.Clear(); - vFPattern.Clear(); - - Refresh(); -} - -Drawing Scatter::GetDrawing() const -{ - DrawingDraw ddw(6*GetSize()); - SetDrawing (ddw, 6); - return ddw; -} - -Image Scatter::GetImage(const int& scale) -{ - bool aa=antialiasing; - antialiasing=false; - ImageDraw idraw(scale*GetSize()); - SetDrawing (idraw,scale); - antialiasing=aa; - return idraw; -} - -#ifdef PLATFORM_WIN32 - -void Scatter::SaveAsMetafile(const char* file) const -{ - WinMetaFileDraw wmfd; - wmfd.Create(6*GetSize().cx,6*GetSize().cy,"Scatter","chart",file); - SetDrawing (wmfd, 6); - wmfd.Close(); -} - -void Scatter::SaveToClipboard(bool saveAsMetafile) -{ - if (saveAsMetafile) { - WinMetaFileDraw wmfd; - wmfd.Create(6*GetSize().cx,6*GetSize().cy,"Scatter","chart"); - SetDrawing (wmfd, 6); - WinMetaFile wmf = wmfd.Close(); - wmf.WriteClipboard(); - } else { - Image img = GetImage(3); - WriteClipboardImage(img); - } -} -#else - -void Scatter::SaveToClipboard(bool) -{ - Image img = GetImage(3); - WriteClipboardImage(img); -} - -#endif - -double Scatter::GetXByPoint(const int x) -{ - return (x-GetH_Border())*GetXRange()/(GetSize().cx-2*GetH_Border()-1)+GetXMin(); -} - -double Scatter::GetYByPoint(const int y) -{ - return (GetSize().cy-GetV_Border()-y-1)*GetYRange()/(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1)+GetYMin(); -} - -double Scatter::GetY2ByPoint(const int y) -{ - return (GetSize().cy-GetV_Border()-y-1)*GetY2Range()/(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1)+GetYMin2(); -} - -double Scatter::GetXPointByValue(const double x) -{ - return (x-GetXMin())/GetXRange()*(GetSize().cx-2*GetH_Border()-1)+GetH_Border(); -} - -double Scatter::GetYPointByValue(const double y) -{ - return (GetSize().cy-GetV_Border()-1)-(y-GetYMin())/GetYRange()*(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1); -} - -void Scatter::Paint(Draw& w) -{ - SetDrawing(w,1); -} - -void Scatter::ShowInfo(bool show) -{ - paintInfo=show; -} - -void Scatter::ProcessPopUp(const Point & pt) -{ - double x=(pt.x-px)*xRange/(GetSize().cx-2*px-1)+xMin; - double y=(GetSize().cy-py-pt.y-1)*yRange/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin; - double y2=(GetSize().cy-py-pt.y-1)*yRange2/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin2; - if(logX) x=pow(10.0, x); - if(logY) y=pow(10.0, y); - if(logY2) y2=pow(10.0, y2); - String strx, stry; - if (cbModifFormatX) - cbModifFormatX(strx, 0, x); - else - strx = VariableFormatX(x); - if (cbModifFormatY) - cbModifFormatY(stry, 0, y); - else - stry = VariableFormatY(y); - String str="x: "+strx+"\ny: "+stry; - if (drawY2Reticle) { - String stry2; - if (cbModifFormatY2) - cbModifFormatY2(stry2, 0, y2); - else - stry2 = VariableFormatY2(y2); - str << "\ny2: "+stry2; - } - const Point p2=pt+offset; - popText.SetText(str).Move(this,p2.x,p2.y); -} - -void Scatter::DoMouseAction(bool down, Point pt, MouseAction action, int value) -{ - switch (action) { - case SCROLL: Scrolling(down, pt); - break; - case ZOOM_H_ENL: - case ZOOM_H_RED: MouseZoom(value, true, false); - break; - case ZOOM_V_ENL: - case ZOOM_V_RED: MouseZoom(value, false, true); - break; - case SHOW_INFO: LabelPopUp(down, pt); - break; - } -} - -bool Scatter::SetMouseBehavior(MouseBehaviour *_mouseBehavior) -{ - if (!_mouseBehavior) - return false; - int i; - for (i = 0; _mouseBehavior[i].action != NO_ACTION && i < MAX_MOUSEBEHAVIOR; ++i) ; - if (i == MAX_MOUSEBEHAVIOR) - return false; - mouseBehavior = _mouseBehavior; - return true; -} - -void Scatter::ProcessMouse(bool down, Point pt, bool ctrl, bool alt, bool shift, bool left, bool middle, int middleWheel, bool right) -{ - int i; - for (i = 0; mouseBehavior[i].action != NO_ACTION && i < MAX_MOUSEBEHAVIOR; ++i) { - if (mouseBehavior[i].ctrl == ctrl && mouseBehavior[i].alt == alt && - mouseBehavior[i].shift == shift && mouseBehavior[i].left == left && - mouseBehavior[i].middle == middle && mouseBehavior[i].right == right && - ((mouseBehavior[i].middleWheel == 0) || mouseBehavior[i].middleWheel == ((middleWheel > 0) - (middleWheel < 0)))) - DoMouseAction(down, pt, mouseBehavior[i].action, middleWheel); - } -} - -void Scatter::LabelPopUp(bool down, Point pt) -{ - if (down) { - if(paintInfo && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) - { - popText.AppearOnly(this); - ProcessPopUp(pt); - isLabelPopUp = true; - } - } else { - if(paintInfo && isLabelPopUp) - { - popText.Close(); - isLabelPopUp = false; - } - } -} - -#ifdef PLATFORM_LINUX - #include -#endif - -void Scatter::Scrolling(bool down, Point pt) -{ - static Image mouseImg; - if (down) { - if((mouseHandlingX || mouseHandlingY) && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) - { - butDownX = pt.x; - butDownY = pt.y; - isScrolling = true; -/* INTERLOCKED { -#ifdef PLATFORM_WIN32 - static Image img = Win32Cursor(IDC_SIZEALL); -#else - static Image img = X11Cursor(XC_fleur); -#endif - mouseImg = Ctrl::OverrideCursor(img); - }*/ - } - } else { - if (isScrolling) { - MouseMove(pt, 0); - isScrolling = false; -// Ctrl::OverrideCursor(mouseImg); - } - } -} - -void Scatter::LeftDown(Point pt, dword keyFlags) -{ - ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, true, false, 0, false); -} - -void Scatter::LeftUp(Point pt, dword keyFlags) -{ - ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, true, false, 0, false); -} - -void Scatter::MiddleDown(Point pt, dword keyFlags) -{ - ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, true, 0, false); -} - -void Scatter::MiddleUp(Point pt, dword keyFlags) -{ - ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, true, 0, false); -} - -void Scatter::RightDown(Point pt, dword keyFlags) -{ - ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, 0, true); -} - -void Scatter::RightUp(Point pt, dword keyFlags) -{ - ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, 0, true); -} - -void Scatter::MouseWheel(Point pt, int zdelta, dword keyFlags) -{ - if (zdelta == 0) - return; - ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, zdelta, false); -} - -void Scatter::MouseMove(Point pt, dword) -{ - if (isScrolling) - { - int shiftX = pt.x - butDownX; - if (mouseHandlingX && shiftX != 0) { - double deltaX = shiftX*xRange/(GetSize().cx - 2*px - 1); - xMin -= deltaX; - xMinUnit += deltaX; - AdjustMinUnitX(); - butDownX = pt.x; - } - int shiftY = pt.y - butDownY; - if (mouseHandlingY && shiftY != 0) { - double deltaY = -shiftY*yRange/(GetSize().cy - 2*py - 1); - yMin -= deltaY; - yMinUnit += deltaY; - AdjustMinUnitY(); - if (drawY2Reticle) { - double deltaY2 = -shiftY*yRange2/(GetSize().cy - 2*py - 1); - yMin2 -= deltaY2; - yMinUnit2 += deltaY2; - AdjustMinUnitY2(); - } - butDownY = pt.y; - } - if ((mouseHandlingX && shiftX != 0) || (mouseHandlingY && shiftY != 0)) { - WhenSetXYMin(); - Refresh(); - WhenZoomScroll(); - } - } - if(isLabelPopUp) { - if (paintInfo && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) - { - ProcessPopUp(pt); - } - } -} - -void Scatter::MouseLeave() -{ - isScrolling = false; -} - -void Scatter::MouseZoom(int zdelta, bool hor, bool ver) -{ - double scale = zdelta > 0 ? zdelta/100. : -100./zdelta; - Zoom(scale); -} - -void Scatter::Zoom(double scale, bool hor, bool ver) -{ - bool mouseX = mouseHandlingX && hor; - mouseX = mouseX && ((minXZoom > 0 && xRange*scale > minXZoom) || (minXZoom < 0)); - mouseX = mouseX && ((maxXZoom > 0 && xRange*scale < maxXZoom) || (maxXZoom < 0)); - bool mouseY = mouseHandlingY && ver; - mouseY = mouseY && ((minYZoom > 0 && yRange*scale > minYZoom) || (minYZoom < 0)); - mouseY = mouseY && ((maxYZoom > 0 && yRange*scale < maxYZoom) || (maxYZoom < 0)); - mouseX = mouseX && (!mouseHandlingY || mouseY); - mouseY = mouseY && (!mouseHandlingX || mouseX); - if (mouseX) - { - double oldXMin = xMin; - xMin += xRange*(1-scale)/2.; - xMinUnit = oldXMin + xMinUnit - xMin; - AdjustMinUnitX(); - xRange *= scale; - } - - if (mouseY) - { - yRange *= scale; - yRange2 *= scale; - } - if (mouseX || mouseY) { - WhenSetRange(); - Refresh(); - WhenZoomScroll(); - } -} - -void Scatter::Scroll(double factorX, double factorY) -{ - if (factorX != 0) { - double deltaX = factorX*xRange; - xMin -= deltaX; - xMinUnit += deltaX; - AdjustMinUnitX(); - } - if (factorY != 0) { - double deltaY = -factorY*yRange; - yMin -= deltaY; - yMinUnit += deltaY; - AdjustMinUnitY(); - if (drawY2Reticle) { - double deltaY2 = -factorY*yRange2; - yMin2 -= deltaY2; - yMinUnit2 += deltaY2; - AdjustMinUnitY2(); - } - } - if (factorX != 0 || factorY != 0) { - Refresh(); - WhenZoomScroll(); - } -} - -Image Scatter::CursorImage(Point p, dword keyflags) -{ - return ChartImg::cursor1(); -} - -void Scatter::Circle(Draw& w, const int& scale, const Point& cp, const int& size, const class::Color& markColor)const -{ - int radius = fround(scale*size/6); int radius2 = radius/2; - w.DrawEllipse(cp.x-radius2, cp.y-radius2, radius, radius, markColor, 1, markColor); -} - -void Scatter::Square(Draw& w, const int& scale, const Point& cp, const int& size, const class::Color& markColor)const -{ - Vector p; - p< p; - p< p; - p< GetLinePattern(String pattern) -{ - Vector ret; - - ret.Add(); - int retPos = 0; - ret[0] = 2; - for (int i = 1; i < pattern.GetCount(); ++i) { - if (pattern[i] != pattern[i-1]) { - ret.Add(); - retPos++; - ret[retPos] = 0; - } - ret[retPos] += 2; - } - return ret; -} - -Vector &GetPatternArray(String pattern) -{ - static VectorMap > pats; - - int pos = pats.Find(pattern); - if (pos < 0) { - pats.Add(pattern, GetLinePattern(pattern)); - pos = pats.GetCount()-1; - } - return pats.GetValues()[pos]; -} - -void Scatter::DrawPolylineX(Draw& w, const Vector &p, int thick, const class::Color &color, String pattern, const int &scale) -{ - if (pattern == LINE_SOLID) - w.DrawPolyline(p, thick, color); - else { - Vector &pat = GetPatternArray(pattern); - int iPat = 0; - - double len = pat[0]*scale; // Pixels por barra - Pointf begin, end; - begin = p[0]; - for (int i = 1; i < p.GetCount();) { - double d = Dist(begin, p[i]); - if (d >= len) - end = PointAtLen(begin, p[i], len); - else { - end = p[i]; - len -= d; - ++i; - } - if (Even(iPat)) - w.DrawLine(begin, end, thick, color); - if (d >= len) { - iPat++; - if (iPat == pat.GetCount()) - iPat = 0; - len = pat[iPat]*scale; - } - begin = end; - } - } -} - -void Scatter::Plot(Draw& w, const int& scale,const int& l,const int& h)const -{ - double d1=xRange/xMajorUnit; - double d2=yRange/yMajorUnit; - - w.DrawRect(1,1,l-2,h-1,plotAreaColor); //grosimea liniei nu este scalata - int gW=fround(gridWidth*scale/6); - if(gridWidth<0) gW=gridWidth; - Vector p; - p.SetCount(2); - if (drawVGrid) - for(int i=0; xMinUnit+i*xMajorUnit < xRange;i++) { - p[0].x = fround(l*xMinUnit/xRange+i*l/d1); p[0].y = 0; - p[1].x = fround(l*xMinUnit/xRange+i*l/d1); p[1].y = h; - DrawPolylineX(w, p, gW, gridColor, "oo..", scale); - } - - if (drawHGrid) - for(int i=0; yMinUnit+i*yMajorUnit < yRange;i++) { - p[0].x = 0; p[0].y = fround(-h*yMinUnit/yRange + h-i*h/d2); - p[1].x = l; p[1].y = fround(-h*yMinUnit/yRange + h-i*h/d2); - DrawPolylineX(w, p, gW, gridColor, "oo..", scale); - } - w.DrawLine(0, h, l, h, scale, Black); - w.DrawLine(0, 0, l, 0, scale, Black); - w.DrawLine(0, 0, 0, h, scale, Black); - w.DrawLine(l, 0, l, h+1, scale, Black); - w.Clip(Rect(0,0,l,h)); - int ix;//int x points coordinates - int iy;//int y points coordinates - if (!vPointsData.IsEmpty()){ - for (int j=0; j p1; - int imin, imax; - if (vPSequential[j]) { - imin = imax = Null; - for (int i = 1; i= xMin) - imin = i-1; - } else if (IsNull(imax)) { - if (vPointsData[j][i].x >= xMin+xRange) - imax = i+1; - } - } - if (IsNull(imin)) - imin = 0; - if (IsNull(imax)) - imax = vPointsData[j].GetCount(); - } else { - imin = 0; - imax = vPointsData[j].GetCount(); - } - int numV; - if (fastViewX) - numV = 1+(imax-imin)/l; - else - numV = 1; - for (int i=imin; i 1) { - yy = 0; - int ii; - for (ii = 0; ii < numV && i+ii < imax; ++ii) - yy += vPointsData[j][i+ii].y; - yy /= double(ii); - xx = (vPointsData[j][i].x + vPointsData[j][i+ii-1].x)/2; - } else { - xx = vPointsData[j][i].x; - yy = vPointsData[j][i].y; - } - ix=fround(l*(xx-xMin)/xRange); - if (vPPrimaryY[j]) - iy=fround(h*(yy-yMin)/yRange); - else - iy=fround(h*(yy-yMin2)/yRange2); - p1<2) - { - Vector p2; - Vector v(Cubic(vPointsData[j])); - for (int i=0; i= 1) { - for (int i=0; i<(imax-imin)/numV; i++) - DrawMark(vMarkStyles[j],w,scale,p1[i],vPWidth[j],vMarkColors[j]); - } - } - } - - int nf=0; //number of functions to draw - - for (int j=0; j p1; - for (int i=0; i p1; - for(int i=0; i Scatter::Cubic(const Vector& DataSet, const int& fineness,double tension) const -{ - Vector OutSet; - if(DataSet.GetCount()>2) { - OutSet<(OutSet); -} - -void ParseTextMultiline(const String &text, Font fnt, Array &texts, Array &sizes) { - Size ret(0, 0); - int npos = 0; - for (int pos = 0; npos != -1; pos = npos+1) { - npos = text.Find('\n', pos); - String &t = texts.Add(); - if (npos != -1) - t = text.Mid(pos, npos-pos); - else - t = text.Mid(pos); - Size &s = sizes.Add(); - s.cx = GetTextSize(t, fnt).cx; - s.cy = GetTextSize(t, fnt).cy; - } -} - -Size GetTextSizeMultiline(Array &sizes) { - Size ret(0, 0); - for (int i = 0; i < sizes.GetCount(); ++i) { - if (sizes[i].cx > ret.cx) - ret.cx = sizes[i].cx; - ret.cy += sizes[i].cy; - } - return ret; -} - -void Scatter::SetDrawing(Draw& w, const int& scale) const -{ - w.DrawRect(scale*GetSize(),graphColor); - Size sz; - sz.cx=0; - sz.cy=0; - if(!title.IsEmpty()) - { - Font FontTitle6; - FontTitle6=titleFont; - FontTitle6.Height(scale*titleFont.GetHeight()); - FontTitle6.Width(scale*titleFont.GetWidth()); - sz= GetTextSize(title, FontTitle6); - w.DrawText((scale*GetSize().cx-sz.cx)/2,scale*2,title,FontTitle6,titleColor); - } - - w.Offset(Point(scale*px,scale*py+scale*titleFont.GetHeight())); - if(showLegend) DrawLegend(w,scale); - int l=scale*GetSize().cx-2*scale*px; - int h=scale*GetSize().cy-2*scale*py-scale*titleFont.GetHeight(); - - Font FontLabel6; - FontLabel6=labelsFont; - FontLabel6.Height(scale*labelsFont.GetHeight()); - - Size lx=GetTextSize(xLabel,FontLabel6); - Size ly=GetTextSize(yLabel,FontLabel6); - Size ly2=GetTextSize(yLabel2,FontLabel6); - w.DrawText(fround((l-lx.cx)/2),h+scale*py-lx.cy-scale*2,xLabel,FontLabel6,labelsColor); - w.DrawText(scale*2-scale*px,fround((h+ly.cx)/2),900,yLabel,FontLabel6,labelsColor); - w.DrawText(fround(l+scale*px-ly2.cy-2*scale),fround((h+ly2.cx)/2),900,yLabel2,FontLabel6,labelsColor); - - if (drawXReticle) - for(int i=0; xMinUnit+i*xMajorUnit<=xRange;i++){ - w.DrawLine(fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit)), - h, - fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit)), - h+scale*4, - fround(scale/2), - axisColor); - Font Standard6; - Standard6.Height(scale*StdFont().GetHeight()); - double gridX=xMinUnit+i*xMajorUnit+xMin; - String gridLabelX; - if (cbModifFormatX) - cbModifFormatX(gridLabelX, i, gridX); - else - gridLabelX = VariableFormatX(gridX); - - Array texts; - Array sizes; - ParseTextMultiline(gridLabelX, StdFont(), texts, sizes); - for (int ii = 0; ii < texts.GetCount(); ++ii) { - int cy = ii == 0 ? 0 : sizes[ii-1].cy; - w.DrawText(fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit) - scale*sizes[ii].cx/2), h+scale*(4+ii*cy), texts[ii], Standard6, axisColor); - } - } - if (drawYReticle) - for(int i=0; yMinUnit+i*yMajorUnit<=yRange;i++){ - w.DrawLine(-(scale*4), - fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit)), - 0, - fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit)), - fround(scale/2), - axisColor); - double gridY=yMinUnit+i*yMajorUnit+yMin; - String gridLabelY; - if (cbModifFormatY) - cbModifFormatY(gridLabelY, i, gridY); - else - gridLabelY = VariableFormatY(gridY); - int dx=scale*GetTextSize(gridLabelY,StdFont()).cx; - Font Standard6; - Standard6.Height(scale*StdFont().GetHeight()); - w.DrawText(-dx-scale*6, fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit))-scale*8, gridLabelY, Standard6, axisColor); - } - if (drawY2Reticle) - for(int i=0; yMinUnit+i*yMajorUnit<=yRange;i++){ - w.DrawLine(l+(scale*4), - fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit)), - l, - fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit)), - fround(scale/2), - axisColor); - double gridY2=yMinUnit2+i*yMajorUnit2+yMin2; - String gridLabelY2; - if (cbModifFormatY2) - cbModifFormatY2(gridLabelY2, i, gridY2); - else - gridLabelY2 = VariableFormatY2(gridY2); - Font Standard6; - Standard6.Height(scale*StdFont().GetHeight()); - w.DrawText(l+scale*10,fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit))-scale*8,gridLabelY2,Standard6,axisColor); - } - - if(antialiasing && w.IsGui()) - { - ImageDraw imdraw(3*l,3*h); - Plot (imdraw,3,3*l,3*h); - w.DrawImage(0,0,l,h,imdraw); - } - else Plot(w,scale,l,h); - - w.End(); -} - -Scatter::Scatter(): - title (""), - titleColor(Black), - graphColor(White), - titleFont(Roman(20)), - xLabel(""),yLabel(""), - labelsFont(StdFont()), - labelsColor(Black), - plotAreaColor(::Color(245,245,248)), - axisColor(Black), - axisWidth(6), - px(30), - py(30), - xRange(100.0), - yRange(100.0), - yRange2(100.0), - xMajorUnit(xRange/10), - yMajorUnit(yRange/5), - xMin(0.0), yMin(0.0), yMin2(0.0), - xMinUnit(0.0), yMinUnit(0.0), yMinUnit2(0.0), - logX(false), logY(false), logY2(false), - cbModifFormatX(NULL),cbModifFormatY(NULL),cbModifFormatY2(NULL), - gridColor(::Color(102,102,102)), - gridWidth(4), - paintInfo(false), - mouseHandlingX(false), mouseHandlingY(false), isScrolling(false), isLabelPopUp(false), - drawXReticle(true), drawYReticle(true), drawY2Reticle(false), - drawVGrid(true), drawHGrid(true), - showLegend(true),legendWeight(80), - antialiasing(false), - offset(10,12), - minXZoom(-1), maxXZoom(-1), minYZoom(-1), maxYZoom(-1), fastViewX(false), sequentialXAll(false) -{ - Color(graphColor); - BackPaint(); - popText.SetColor(::Color(200,220,255)); - SetMouseBehavior(defaultMouse); -} - -Scatter::~Scatter() -{ -} - +#include "Scatter.h" + +#define IMAGECLASS ChartImg +#define IMAGEFILE +#include + +Scatter::MouseBehaviour defaultMouse[] = { + {false, false, false, true , false, 0, false, Scatter::SHOW_INFO}, + {false, false, false, false, true , 0, false, Scatter::SCROLL}, + {false, false, false, false, false, 1, false, Scatter::ZOOM_H_RED}, + {false, false, false, false, false, 1, false, Scatter::ZOOM_V_RED}, + {false, false, false, false, false,-1, false, Scatter::ZOOM_H_ENL}, + {false, false, false, false, false,-1, false, Scatter::ZOOM_V_ENL}, + {false, false, false, false, false, 0, false, Scatter::NO_ACTION}}; + + +Scatter& Scatter::SetColor(const class::Color& _color) +{ + graphColor=_color; + return *this; +} + +Scatter& Scatter::SetTitle(const String& _title) +{ + title=_title; + return *this; +} +Scatter& Scatter::SetTitleFont(const Font& fontTitle) +{ + titleFont=fontTitle; + return *this; +} +Scatter& Scatter::SetTitleColor(const class::Color& colorTitle) +{ + titleColor=colorTitle; + return *this; +} +void Scatter::SetLabels(const WString& _xLabel, const WString& _yLabel, const WString& _yLabel2) +{ + xLabel=_xLabel; + yLabel=_yLabel; + yLabel2=_yLabel2; +} +Scatter& Scatter::SetLabelX(const WString& _xLabel) +{ + xLabel=_xLabel; + return *this; +} +Scatter& Scatter::SetLabelY(const WString& _yLabel) +{ + yLabel=_yLabel; + return *this; +} +Scatter& Scatter::SetLabelY2(const WString& _yLabel) +{ + yLabel2=_yLabel; + return *this; +} +Scatter& Scatter::SetLabelsFont(const Font& fontLabels) +{ + labelsFont=fontLabels; + return *this; +} +Scatter& Scatter::SetLabelsColor(const class::Color& colorLabels) +{ + labelsColor=colorLabels; + return *this; +} +Scatter& Scatter::SetPlotAreaPoz(const int& poz_x, const int& poz_y) +{ + px=poz_x; + py=poz_y; + return *this; +} +Scatter& Scatter::H_Border(const int& poz_x) +{ + if(poz_x>=0) px=poz_x; + return *this; +} +Scatter& Scatter::V_Border(const int& poz_y) +{ + if(poz_y>=0) py=poz_y; + return *this; +} + +Scatter& Scatter::SetPlotAreaColor(const class::Color& p_a_color) +{ + plotAreaColor=p_a_color; + return *this; +} +Scatter& Scatter::SetAxisColor(const class::Color& axis_color) +{ + axisColor=axis_color; + return *this; +} +Scatter& Scatter::SetAxisWidth(const int& axis_width) +{ + axisWidth=axis_width; + return *this; +} +Scatter& Scatter::SetGridColor(const class::Color& grid_color) +{ + gridColor=grid_color; + return *this; +} +Scatter& Scatter::SetGridWidth(const int& grid_width) +{ + gridWidth=grid_width; + return *this; +} +Scatter& Scatter::ShowHGrid(const bool& show) +{ + drawHGrid=show; + return *this; +} +Scatter& Scatter::ShowVGrid(const bool& show) +{ + drawVGrid=show; + return *this; +} +Scatter& Scatter::ShowLegend(const bool& show) +{ + showLegend=show; + return *this; +} +Scatter& Scatter::SetLegendWeight(const int& weight) +{ + legendWeight=weight; + return *this; +} +Scatter& Scatter::SetAntialiasing(const bool& aa) +{ + antialiasing=aa; + return *this; +} +Scatter &Scatter::SetDrawXReticle(bool set) +{ + drawXReticle = set; + return *this; +} +Scatter &Scatter::SetDrawYReticle(bool set) +{ + drawYReticle = set; + return *this; +} +Scatter &Scatter::SetDrawY2Reticle(bool set) +{ + drawY2Reticle = set; + return *this; +} +void Scatter::DrawLegend(Draw& w,const int& scale) const +{ + Vector L; + L.Append(vLegend); + L.Append(vFLegend); + Vector Thick; + Thick.Append(vPThickness); + Thick.Append(vFThickness); + Vector LC; + LC.Append(vPColors); + LC.Append(vFColors); + Vector LW; + LW.Append(vPWidth); + VectorVJ; + VJ.Append(vJoin); + Vector MS; + MS.Append(vMarkStyles); + Vector MC; + MC.Append(vMarkColors); + Vector Patt; + Patt.Append(vPPattern); + Patt.Append(vFPattern); + + int NMR=fround((GetSize().cx-2*px)/legendWeight);//max number of labels per row + if (NMR>0) + { + int N=L.GetCount();//number of labels + int Nc;//number of complete rows + int LCR;//number of labels on complete row + int R;//number of remaining labels on incomplete row + if(NMR>N) {Nc=0; LCR=0; R=N;} + else if (NMR==N) {Nc=1; LCR=N; R=0;} + else {Nc=N/NMR; LCR=NMR; R=N%NMR;} + for(int j=0;j<=Nc;j++) + { + int start=N-(j+1)*LCR; + int end=N-j*LCR; + if (j==Nc) {start=0; end=R;} + for(int i=start;i vp; + vp << Point(scale*(i-start)*legendWeight, scale*(4-12*(j+1))) << + Point(scale*(i-start)*legendWeight+scale*23, scale*(4-12*(j+1))); + if (VJ.At(i)) + DrawPolylineX(w, vp, scale*Thick.At(i)/6, LC.At(i), Patt.At(i), scale); + Point p(scale*((i-start)*legendWeight+7),scale*(4-12*(j+1))/*+scale*Thick.At(i)/12*/); + if (LW.At(i,0) > 1) + DrawMark(MS.At(i),w,scale,p,LW.At(i,0),MC.At(i)); + Font scaledFont; + scaledFont.Height(scale*StdFont().GetHeight()); + w.DrawText(scale*(i-start)*legendWeight+scale*25, + scale*(-2-12*(j+1)), + L.At(i), + scaledFont,LC.At(i)); + } + } + } +} + +void Scatter::AdjustMinUnitX() +{ + while (xMinUnit < 0) + xMinUnit += xMajorUnit; + while (xMinUnit > xMajorUnit) + xMinUnit -= xMajorUnit; +} +void Scatter::AdjustMinUnitY() +{ + while (yMinUnit < 0) + yMinUnit += yMajorUnit; + while (yMinUnit > yMajorUnit) + yMinUnit -= yMajorUnit; +} +void Scatter::AdjustMinUnitY2() +{ + if (yMajorUnit2 > 0) { + while (yMinUnit2 < 0) + yMinUnit2 += yMajorUnit2; + while (yMinUnit2 > yMajorUnit2) + yMinUnit2 -= yMajorUnit2; + } +} +Scatter &Scatter::SetRange(double rx, double ry, double ry2) +{ + xRange=rx; + yRange=ry; + yRange2=ry2; + xMajorUnit=xRange/10; + AdjustMinUnitX(); + yMajorUnit=yRange/10; + AdjustMinUnitY(); + yMajorUnit2=yRange2/10; + AdjustMinUnitY2(); + WhenSetRange(); + return *this; +} +Scatter &Scatter::SetMajorUnits(double ux, double uy) +{ + //if (ux > xRange) throw (Exc(t_("Invalid X major units!"))); + //if (uy > yRange) throw (Exc(t_("Invalid Y major units!"))); + xMajorUnit=ux; + yMajorUnit=uy; + yMajorUnit2=yRange2*yMajorUnit/yRange; + AdjustMinUnitX(); + AdjustMinUnitY(); + AdjustMinUnitY2(); + return *this; +} +Scatter &Scatter::SetMinUnits(double ux, double uy) +{ + xMinUnit=ux; + yMinUnit=uy; + yMinUnit2=yRange2*yMinUnit/yRange; + AdjustMinUnitX(); + AdjustMinUnitY(); + AdjustMinUnitY2(); + return *this; +} +Scatter &Scatter::SetXYMin(double xmin, double ymin, double ymin2) +{ + xMin=xmin; + yMin=ymin; + yMin2=ymin2; + WhenSetXYMin(); + return *this; +} + +void Scatter::FitToData(bool Y) { + double minx, maxx, miny, miny2, maxy, maxy2; + minx = miny = miny2 = -DOUBLE_NULL; + maxx = maxy = maxy2 = DOUBLE_NULL; + + for (int j=0; j maxx) + maxx = vPointsData[j][i].x; + } + } + for (int j=0; j maxy) + maxy = vPointsData[j][i].y; + } else { + if (vPointsData[j][i].y < miny2) + miny2 = vPointsData[j][i].y; + if (vPointsData[j][i].y > maxy2) + maxy2 = vPointsData[j][i].y; + } + } + } + for (int j=0; j & points,const String& legend,const bool& join, const class::Color& pcolor, const int& width, const int& thickness) +{ + vPointsData.AddPick(points); + vJoin.Add(join); + vSmooth.Add(false); + vPColors.Add(pcolor); + vPWidth.Add(width); + vPThickness.Add(thickness); + vLegend.Add(legend); + vMarkColors.Add(pcolor); + if (width <= 1) + vShowMark.Add(false); + else + vShowMark.Add(true); + vMarkStyles.Add(CIRCLE); + vPPrimaryY.Add(true); + vPSequential.Add(sequentialXAll); + vPPattern.Add(LINE_SOLID); + + Refresh(); + return *this; +} + +Scatter &Scatter::SetPattern(const String pattern) +{ + vPPattern[vPPattern.GetCount()-1] = pattern; + return *this; +} + +void Scatter::AddPoint(const int& j, const XY & point, const bool& refresh) +{ + if(IsValid(j)) + { + vPointsData[j].Add(point); + if(refresh) Refresh(); + } +} +void Scatter::InsertPoint(const int& j, const int& i, const XY & point) +{ + if(IsValid(j)) + { + if(i>=0 && vPointsData[j].GetCount()>=i) + { + vPointsData[j].Insert(i,point); + Refresh(); + } + } +} +void Scatter::RemovePoint(const int& j, const int& i) +{ + if(IsValid(j)) + { + if(i>=0 && vPointsData[j].GetCount()>i) + { + vPointsData[j].Remove(i); + Refresh(); + } + } +} +void Scatter::SetData(const int& j, const int& i, const XY & point) +{ + if(IsValid(j)) + { + if(i>=0 && vPointsData[j].GetCount()>i) + { + vPointsData[j][i]=point; + Refresh(); + } + } +} + +void Scatter::SetData(const int& j, Vector & points) +{ + if(IsValid(j)) + { + vPointsData[j]<<=points; + Refresh(); + } +} +void Scatter::SetDataColor(const int& j, const class::Color& pcolor) +{ + if(IsValid(j)) + { + vPColors[j]=pcolor; + Refresh(); + } +} +void Scatter::SetFunctColor(const int& j, const class::Color& fcolor) +{ + if(IsValid(j)) + { + vFColors[j]=fcolor; + Refresh(); + } +} +Color Scatter::GetDataColor(const int& j) const +{ + if(IsValid(j)) + { + return vPColors[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +Color Scatter::GetFunctColor(const int& j) const +{ + if(IsValid(j)) + { + return vFColors[j]; + } + throw (Exc(t_("Invalid function index!"))); +} + +void Scatter::SetDataThickness(const int& j, const int& thick_dots) +{ + if(IsValid(j)) + { + vPThickness[j]=thick_dots; + Refresh(); + } +} + +void Scatter::SetFunctThickness(const int& j, const int& thick_dots) +{ + if(IsValid(j)) + { + vFThickness[j]=thick_dots; + Refresh(); + } +} +int Scatter::GetDataThickness(const int& j) const +{ + if(IsValid(j)) + { + return vPThickness[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +int Scatter::GetFunctThickness(const int& j) const +{ + if(IsValid(j)) + { + return vFThickness[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +void Scatter::SetMarkWidth(const int& j, const int& width_dots) +{ + if(IsValid(j)) + { + vPWidth[j]=width_dots; + Refresh(); + } +} + +int Scatter::GetMarkWidth(const int& j) const +{ + if(IsValid(j)) + { + return vPWidth[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +void Scatter::SetMarkStyle(const int& j, MarkStyle noStyle) +{ + if(IsValid(j)) + { + vMarkStyles[j]=noStyle; + Refresh(); + } +} + +int Scatter::GetMarkStyle(const int& j) const +{ + if(IsValid(j)) + { + return vMarkStyles[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +void Scatter::SetMarkColor(const int& j, const ::Color& mcolor) +{ + if(IsValid(j)) + { + vMarkColors[j]=mcolor; + Refresh(); + } +} + +Color Scatter::GetMarkColor(const int& j) const +{ + if(IsValid(j)) + { + return vMarkColors[j]; + } + throw (Exc(t_("Invalid series index!"))); +} + +void Scatter::SetShowMark(const int& j, const bool& show) +{ + if(IsValid(j)) + { + vShowMark[j]=show; + Refresh(); + } +} + +bool Scatter::IsMarkShow(const int& j) const throw (Exc) +{ + if(!IsValid(j)) throw (Exc(t_("Invalid series index!"))); + return vShowMark[j]; +} + +void Scatter::SetJoin(const int& j, const bool& join) +{ + if(IsValid(j)) + { + vJoin[j]=join; + Refresh(); + } +} + +bool Scatter::IsJoined(const int& j) const throw (Exc) +{ + if(!IsValid(j)) throw (Exc(t_("Invalid series index!"))); + + return vJoin[j]; +} + +void Scatter::SetSmooth(const int& j, const bool& smooth) +{ + if(IsValid(j)) + { + vSmooth[j]=smooth; + Refresh(); + } +} + +bool Scatter::IsSmooth(const int& j) const throw (Exc) +{ + if(!IsValid(j)) throw (Exc(t_("Invalid series index!"))); + + return vSmooth[j]; +} + +void Scatter::SetDataPrimaryY(const int& j, const bool& primary) +{ + if(IsValid(j)) + { + vPPrimaryY[j]=primary; + Refresh(); + } +} + +Scatter &Scatter::SetDataPrimaryY(const bool& primary) +{ + SetDataPrimaryY(vPPrimaryY.GetCount()-1, primary); + return *this; +} + +bool Scatter::IsDataPrimaryY(const int& j) const throw (Exc) +{ + if(!IsValid(j)) throw (Exc(t_("Invalid series index!"))); + + return vPPrimaryY[j]; +} + +void Scatter::SetSequentialX(const int& j, const bool& sequential) +{ + if(IsValid(j)) + { + vPSequential[j]=sequential; + Refresh(); + } +} + +Scatter &Scatter::SetSequentialX(const bool& sequential) +{ + SetSequentialX(vPSequential.GetCount()-1, sequential); + return *this; +} + +Scatter &Scatter::SetSequentialXAll(const bool& sequential) +{ + for (int i = 0; i < vPSequential.GetCount(); ++i) + SetSequentialX(i, sequential); + sequentialXAll = sequential; + return *this; +} + +void Scatter::SetFunctPrimaryY(const int& j, const bool& primary) +{ + if(IsValid(j)) + { + vFPrimaryY[j]=primary; + Refresh(); + } +} + +Scatter &Scatter::SetFunctPrimaryY(const bool& primary) +{ + SetFunctPrimaryY(vFPrimaryY.GetCount()-1, primary); + return *this; +} + +bool Scatter::IsFunctPrimaryY(const int& j) const throw (Exc) +{ + if(!IsValid(j)) throw (Exc(t_("Invalid series index!"))); + + return vFPrimaryY[j]; +} + +void Scatter::RemoveSeries(const int& j) +{ + if (IsValid(j)) + { + vPointsData.Remove(j); + vJoin.Remove(j); + vSmooth.Remove(j); + vPColors.Remove(j); + vPWidth.Remove(j); + vPThickness.Remove(j); + vLegend.Remove(j); + vMarkColors.Remove(j); + vShowMark.Remove(j); + vMarkStyles.Remove(j); + vPPrimaryY.Remove(j); + vPPattern.Remove(j); + vPSequential.Remove(j); + + Refresh(); + } +} + +void Scatter::RemoveAllSeries() +{ + vPointsData.Clear(); + vJoin.Clear(); + vSmooth.Clear(); + vPColors.Clear(); + vPWidth.Clear(); + vPThickness.Clear(); + vLegend.Clear(); + vMarkColors.Clear(); + vShowMark.Clear(); + vMarkStyles.Clear(); + vPPrimaryY.Clear(); + vPSequential.Clear(); + vPPattern.Clear(); + + Refresh(); +} + + +void Scatter::PlotFunction(double (*f)(double), const String& legend, const class::Color& fcolor, const int& weight) +{ + Vector series; + vFunctionData.AddPick(series); + + vAdress.Add(f); + + vFColors.Add(fcolor); + vFThickness.Add(weight); + vFLegend.Add(legend); + vFPrimaryY.Add(true); + vFPattern.Add(LINE_SOLID); + Refresh(); +} +void Scatter::PlotParaFunction(XY (*pf)(double), const String& legend, const class::Color& fcolor, const int& weight,const int& Np) +{ + double t;//t must be choosed between [0,1] + Vector series; + for (int i=0; i<=Np;i++) + { + t=(double)i/Np; + series<j) + { + if(vFunctionData[j].IsEmpty()) + { + int nf=-1; + for(int i=0; i<=j; i++) + { + if (vFunctionData[i].IsEmpty()) nf++; + } + vAdress.Remove(nf); + } + + vFunctionData.Remove(j); + vFColors.Remove(j); + vFThickness.Remove(j); + vFLegend.Remove(j); + vFPrimaryY.Remove(j); + vFPattern.Remove(j); + + Refresh(); + } +} + +void Scatter::RemoveAllFSeries() +{ + vAdress.Clear(); + vFunctionData.Clear(); + vFColors.Clear(); + vFThickness.Clear(); + vFLegend.Clear(); + vFPrimaryY.Clear(); + vFPattern.Clear(); + + Refresh(); +} + +Drawing Scatter::GetDrawing() const +{ + DrawingDraw ddw(6*GetSize()); + SetDrawing (ddw, 6); + return ddw; +} + +Image Scatter::GetImage(const int& scale) +{ + bool aa=antialiasing; + antialiasing=false; + ImageDraw idraw(scale*GetSize()); + SetDrawing (idraw,scale); + antialiasing=aa; + return idraw; +} + +#ifdef PLATFORM_WIN32 + +void Scatter::SaveAsMetafile(const char* file) const +{ + WinMetaFileDraw wmfd; + wmfd.Create(6*GetSize().cx,6*GetSize().cy,"Scatter","chart",file); + SetDrawing (wmfd, 6); + wmfd.Close(); +} + +void Scatter::SaveToClipboard(bool saveAsMetafile) +{ + if (saveAsMetafile) { + WinMetaFileDraw wmfd; + wmfd.Create(6*GetSize().cx,6*GetSize().cy,"Scatter","chart"); + SetDrawing (wmfd, 6); + WinMetaFile wmf = wmfd.Close(); + wmf.WriteClipboard(); + } else { + Image img = GetImage(3); + WriteClipboardImage(img); + } +} +#else + +void Scatter::SaveToClipboard(bool) +{ + Image img = GetImage(3); + WriteClipboardImage(img); +} + +#endif + +double Scatter::GetXByPoint(const int x) +{ + return (x-GetH_Border())*GetXRange()/(GetSize().cx-2*GetH_Border()-1)+GetXMin(); +} + +double Scatter::GetYByPoint(const int y) +{ + return (GetSize().cy-GetV_Border()-y-1)*GetYRange()/(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1)+GetYMin(); +} + +double Scatter::GetY2ByPoint(const int y) +{ + return (GetSize().cy-GetV_Border()-y-1)*GetY2Range()/(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1)+GetYMin2(); +} + +double Scatter::GetXPointByValue(const double x) +{ + return (x-GetXMin())/GetXRange()*(GetSize().cx-2*GetH_Border()-1)+GetH_Border(); +} + +double Scatter::GetYPointByValue(const double y) +{ + return (GetSize().cy-GetV_Border()-1)-(y-GetYMin())/GetYRange()*(GetSize().cy-2*GetV_Border()-GetTitleFont().GetHeight()-1); +} + +void Scatter::Paint(Draw& w) +{ + SetDrawing(w,1); +} + +void Scatter::ShowInfo(bool show) +{ + paintInfo=show; +} + +void Scatter::ProcessPopUp(const Point & pt) +{ + double x=(pt.x-px)*xRange/(GetSize().cx-2*px-1)+xMin; + double y=(GetSize().cy-py-pt.y-1)*yRange/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin; + double y2=(GetSize().cy-py-pt.y-1)*yRange2/(GetSize().cy-2*py-titleFont.GetHeight()-1)+yMin2; + if(logX) x=pow(10.0, x); + if(logY) y=pow(10.0, y); + if(logY2) y2=pow(10.0, y2); + String strx, stry; + if (cbModifFormatX) + cbModifFormatX(strx, 0, x); + else + strx = VariableFormatX(x); + if (cbModifFormatY) + cbModifFormatY(stry, 0, y); + else + stry = VariableFormatY(y); + String str="x: "+strx+"\ny: "+stry; + if (drawY2Reticle) { + String stry2; + if (cbModifFormatY2) + cbModifFormatY2(stry2, 0, y2); + else + stry2 = VariableFormatY2(y2); + str << "\ny2: "+stry2; + } + const Point p2=pt+offset; + popText.SetText(str).Move(this,p2.x,p2.y); +} + +void Scatter::DoMouseAction(bool down, Point pt, MouseAction action, int value) +{ + switch (action) { + case SCROLL: Scrolling(down, pt); + break; + case ZOOM_H_ENL: + case ZOOM_H_RED: MouseZoom(value, true, false); + break; + case ZOOM_V_ENL: + case ZOOM_V_RED: MouseZoom(value, false, true); + break; + case SHOW_INFO: LabelPopUp(down, pt); + break; + } +} + +bool Scatter::SetMouseBehavior(MouseBehaviour *_mouseBehavior) +{ + if (!_mouseBehavior) + return false; + int i; + for (i = 0; _mouseBehavior[i].action != NO_ACTION && i < MAX_MOUSEBEHAVIOR; ++i) ; + if (i == MAX_MOUSEBEHAVIOR) + return false; + mouseBehavior = _mouseBehavior; + return true; +} + +void Scatter::ProcessMouse(bool down, Point pt, bool ctrl, bool alt, bool shift, bool left, bool middle, int middleWheel, bool right) +{ + int i; + for (i = 0; mouseBehavior[i].action != NO_ACTION && i < MAX_MOUSEBEHAVIOR; ++i) { + if (mouseBehavior[i].ctrl == ctrl && mouseBehavior[i].alt == alt && + mouseBehavior[i].shift == shift && mouseBehavior[i].left == left && + mouseBehavior[i].middle == middle && mouseBehavior[i].right == right && + ((mouseBehavior[i].middleWheel == 0) || mouseBehavior[i].middleWheel == ((middleWheel > 0) - (middleWheel < 0)))) + DoMouseAction(down, pt, mouseBehavior[i].action, middleWheel); + } +} + +void Scatter::LabelPopUp(bool down, Point pt) +{ + if (down) { + if(paintInfo && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) + { + popText.AppearOnly(this); + ProcessPopUp(pt); + isLabelPopUp = true; + } + } else { + if(paintInfo && isLabelPopUp) + { + popText.Close(); + isLabelPopUp = false; + } + } +} + +#ifdef PLATFORM_LINUX + #include +#endif + +void Scatter::Scrolling(bool down, Point pt) +{ + static Image mouseImg; + if (down) { + if((mouseHandlingX || mouseHandlingY) && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) + { + butDownX = pt.x; + butDownY = pt.y; + isScrolling = true; + INTERLOCKED { +#ifdef PLATFORM_WIN32 + static Image img = Win32Cursor(IDC_SIZEALL); +#else + static Image img = X11Cursor(XC_fleur); +#endif + mouseImg = Ctrl::OverrideCursor(img); + } + } + } else { + if (isScrolling) { + MouseMove(pt, 0); + isScrolling = false; + Ctrl::OverrideCursor(mouseImg); + } + } +} + +void Scatter::LeftDown(Point pt, dword keyFlags) +{ + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, true, false, 0, false); +} + +void Scatter::LeftUp(Point pt, dword keyFlags) +{ + ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, true, false, 0, false); +} + +void Scatter::MiddleDown(Point pt, dword keyFlags) +{ + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, true, 0, false); +} + +void Scatter::MiddleUp(Point pt, dword keyFlags) +{ + ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, true, 0, false); +} + +void Scatter::RightDown(Point pt, dword keyFlags) +{ + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, 0, true); +} + +void Scatter::RightUp(Point pt, dword keyFlags) +{ + ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, 0, true); +} + +void Scatter::MouseWheel(Point pt, int zdelta, dword keyFlags) +{ + if (zdelta == 0) + return; + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, zdelta, false); +} + +void Scatter::MouseMove(Point pt, dword) +{ + if (isScrolling) + { + int shiftX = pt.x - butDownX; + if (mouseHandlingX && shiftX != 0) { + double deltaX = shiftX*xRange/(GetSize().cx - 2*px - 1); + xMin -= deltaX; + xMinUnit += deltaX; + AdjustMinUnitX(); + butDownX = pt.x; + } + int shiftY = pt.y - butDownY; + if (mouseHandlingY && shiftY != 0) { + double deltaY = -shiftY*yRange/(GetSize().cy - 2*py - 1); + yMin -= deltaY; + yMinUnit += deltaY; + AdjustMinUnitY(); + if (drawY2Reticle) { + double deltaY2 = -shiftY*yRange2/(GetSize().cy - 2*py - 1); + yMin2 -= deltaY2; + yMinUnit2 += deltaY2; + AdjustMinUnitY2(); + } + butDownY = pt.y; + } + if ((mouseHandlingX && shiftX != 0) || (mouseHandlingY && shiftY != 0)) { + WhenSetXYMin(); + Refresh(); + WhenZoomScroll(); + } + } + if(isLabelPopUp) { + if (paintInfo && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) + { + ProcessPopUp(pt); + } + } +} + +void Scatter::MouseLeave() +{ + isScrolling = false; +} + +void Scatter::MouseZoom(int zdelta, bool hor, bool ver) +{ + double scale = zdelta > 0 ? zdelta/100. : -100./zdelta; + Zoom(scale); +} + +void Scatter::Zoom(double scale, bool hor, bool ver) +{ + bool mouseX = mouseHandlingX && hor; + mouseX = mouseX && ((minXZoom > 0 && xRange*scale > minXZoom) || (minXZoom < 0)); + mouseX = mouseX && ((maxXZoom > 0 && xRange*scale < maxXZoom) || (maxXZoom < 0)); + bool mouseY = mouseHandlingY && ver; + mouseY = mouseY && ((minYZoom > 0 && yRange*scale > minYZoom) || (minYZoom < 0)); + mouseY = mouseY && ((maxYZoom > 0 && yRange*scale < maxYZoom) || (maxYZoom < 0)); + mouseX = mouseX && (!mouseHandlingY || mouseY); + mouseY = mouseY && (!mouseHandlingX || mouseX); + if (mouseX) + { + double oldXMin = xMin; + xMin += xRange*(1-scale)/2.; + xMinUnit = oldXMin + xMinUnit - xMin; + AdjustMinUnitX(); + xRange *= scale; + } + + if (mouseY) + { + yRange *= scale; + yRange2 *= scale; + } + if (mouseX || mouseY) { + WhenSetRange(); + Refresh(); + WhenZoomScroll(); + } +} + +void Scatter::Scroll(double factorX, double factorY) +{ + if (factorX != 0) { + double deltaX = factorX*xRange; + xMin -= deltaX; + xMinUnit += deltaX; + AdjustMinUnitX(); + } + if (factorY != 0) { + double deltaY = -factorY*yRange; + yMin -= deltaY; + yMinUnit += deltaY; + AdjustMinUnitY(); + if (drawY2Reticle) { + double deltaY2 = -factorY*yRange2; + yMin2 -= deltaY2; + yMinUnit2 += deltaY2; + AdjustMinUnitY2(); + } + } + if (factorX != 0 || factorY != 0) { + Refresh(); + WhenZoomScroll(); + } +} + +Image Scatter::CursorImage(Point p, dword keyflags) +{ + return ChartImg::cursor1(); +} + +void Scatter::Circle(Draw& w, const int& scale, const Point& cp, const int& size, const class::Color& markColor)const +{ + int radius = fround(scale*size/6); int radius2 = radius/2; + w.DrawEllipse(cp.x-radius2, cp.y-radius2, radius, radius, markColor, 1, markColor); +} + +void Scatter::Square(Draw& w, const int& scale, const Point& cp, const int& size, const class::Color& markColor)const +{ + Vector p; + p< p; + p< p; + p< GetLinePattern(String pattern) +{ + Vector ret; + + ret.Add(); + int retPos = 0; + ret[0] = 2; + for (int i = 1; i < pattern.GetCount(); ++i) { + if (pattern[i] != pattern[i-1]) { + ret.Add(); + retPos++; + ret[retPos] = 0; + } + ret[retPos] += 2; + } + return ret; +} + +Vector &GetPatternArray(String pattern) +{ + static VectorMap > pats; + + int pos = pats.Find(pattern); + if (pos < 0) { + pats.Add(pattern, GetLinePattern(pattern)); + pos = pats.GetCount()-1; + } + return pats.GetValues()[pos]; +} + +void Scatter::DrawPolylineX(Draw& w, const Vector &p, int thick, const class::Color &color, String pattern, const int &scale) +{ + if (pattern == LINE_SOLID) + w.DrawPolyline(p, thick, color); + else { + Vector &pat = GetPatternArray(pattern); + int iPat = 0; + + double len = pat[0]*scale; // Pixels por barra + Pointf begin, end; + begin = p[0]; + for (int i = 1; i < p.GetCount();) { + double d = Dist(begin, p[i]); + if (d >= len) + end = PointAtLen(begin, p[i], len); + else { + end = p[i]; + len -= d; + ++i; + } + if (Even(iPat)) + w.DrawLine(begin, end, thick, color); + if (d >= len) { + iPat++; + if (iPat == pat.GetCount()) + iPat = 0; + len = pat[iPat]*scale; + } + begin = end; + } + } +} + +void Scatter::Plot(Draw& w, const int& scale,const int& l,const int& h)const +{ + double d1=xRange/xMajorUnit; + double d2=yRange/yMajorUnit; + + w.DrawRect(1,1,l-2,h-1,plotAreaColor); //grosimea liniei nu este scalata + int gW=fround(gridWidth*scale/6); + if(gridWidth<0) gW=gridWidth; + Vector p; + p.SetCount(2); + if (drawVGrid) + for(int i=0; xMinUnit+i*xMajorUnit < xRange;i++) { + p[0].x = fround(l*xMinUnit/xRange+i*l/d1); p[0].y = 0; + p[1].x = fround(l*xMinUnit/xRange+i*l/d1); p[1].y = h; + DrawPolylineX(w, p, gW, gridColor, "oo..", scale); + } + + if (drawHGrid) + for(int i=0; yMinUnit+i*yMajorUnit < yRange;i++) { + p[0].x = 0; p[0].y = fround(-h*yMinUnit/yRange + h-i*h/d2); + p[1].x = l; p[1].y = fround(-h*yMinUnit/yRange + h-i*h/d2); + DrawPolylineX(w, p, gW, gridColor, "oo..", scale); + } + w.DrawLine(0, h, l, h, scale, Black); + w.DrawLine(0, 0, l, 0, scale, Black); + w.DrawLine(0, 0, 0, h, scale, Black); + w.DrawLine(l, 0, l, h+1, scale, Black); + w.Clip(Rect(0,0,l,h)); + int ix;//int x points coordinates + int iy;//int y points coordinates + if (!vPointsData.IsEmpty()){ + for (int j=0; j p1; + int imin, imax; + if (vPSequential[j]) { + imin = imax = Null; + for (int i = 1; i= xMin) + imin = i-1; + } else if (IsNull(imax)) { + if (vPointsData[j][i].x >= xMin+xRange) + imax = i+1; + } + } + if (IsNull(imin)) + imin = 0; + if (IsNull(imax)) + imax = vPointsData[j].GetCount(); + } else { + imin = 0; + imax = vPointsData[j].GetCount(); + } + int numV; + if (fastViewX) + numV = 1+(imax-imin)/l; + else + numV = 1; + for (int i=imin; i 1) { + yy = 0; + int ii; + for (ii = 0; ii < numV && i+ii < imax; ++ii) + yy += vPointsData[j][i+ii].y; + yy /= double(ii); + xx = (vPointsData[j][i].x + vPointsData[j][i+ii-1].x)/2; + } else { + xx = vPointsData[j][i].x; + yy = vPointsData[j][i].y; + } + ix=fround(l*(xx-xMin)/xRange); + if (vPPrimaryY[j]) + iy=fround(h*(yy-yMin)/yRange); + else + iy=fround(h*(yy-yMin2)/yRange2); + p1<2) + { + Vector p2; + Vector v(Cubic(vPointsData[j])); + for (int i=0; i= 1) { + for (int i=0; i<(imax-imin)/numV; i++) + DrawMark(vMarkStyles[j],w,scale,p1[i],vPWidth[j],vMarkColors[j]); + } + } + } + + int nf=0; //number of functions to draw + + for (int j=0; j p1; + for (int i=0; i p1; + for(int i=0; i Scatter::Cubic(const Vector& DataSet, const int& fineness,double tension) const +{ + Vector OutSet; + if(DataSet.GetCount()>2) { + OutSet<(OutSet); +} + +void ParseTextMultiline(const String &text, Font fnt, Array &texts, Array &sizes) { + Size ret(0, 0); + int npos = 0; + for (int pos = 0; npos != -1; pos = npos+1) { + npos = text.Find('\n', pos); + String &t = texts.Add(); + if (npos != -1) + t = text.Mid(pos, npos-pos); + else + t = text.Mid(pos); + Size &s = sizes.Add(); + s.cx = GetTextSize(t, fnt).cx; + s.cy = GetTextSize(t, fnt).cy; + } +} + +Size GetTextSizeMultiline(Array &sizes) { + Size ret(0, 0); + for (int i = 0; i < sizes.GetCount(); ++i) { + if (sizes[i].cx > ret.cx) + ret.cx = sizes[i].cx; + ret.cy += sizes[i].cy; + } + return ret; +} + +void Scatter::SetDrawing(Draw& w, const int& scale) const +{ + w.DrawRect(scale*GetSize(),graphColor); + Size sz; + sz.cx=0; + sz.cy=0; + if(!title.IsEmpty()) + { + Font FontTitle6; + FontTitle6=titleFont; + FontTitle6.Height(scale*titleFont.GetHeight()); + FontTitle6.Width(scale*titleFont.GetWidth()); + sz= GetTextSize(title, FontTitle6); + w.DrawText((scale*GetSize().cx-sz.cx)/2,scale*2,title,FontTitle6,titleColor); + } + + w.Offset(Point(scale*px,scale*py+scale*titleFont.GetHeight())); + if(showLegend) DrawLegend(w,scale); + int l=scale*GetSize().cx-2*scale*px; + int h=scale*GetSize().cy-2*scale*py-scale*titleFont.GetHeight(); + + Font FontLabel6; + FontLabel6=labelsFont; + FontLabel6.Height(scale*labelsFont.GetHeight()); + + Size lx=GetTextSize(xLabel,FontLabel6); + Size ly=GetTextSize(yLabel,FontLabel6); + Size ly2=GetTextSize(yLabel2,FontLabel6); + w.DrawText(fround((l-lx.cx)/2),h+scale*py-lx.cy-scale*2,xLabel,FontLabel6,labelsColor); + w.DrawText(scale*2-scale*px,fround((h+ly.cx)/2),900,yLabel,FontLabel6,labelsColor); + w.DrawText(fround(l+scale*px-ly2.cy-2*scale),fround((h+ly2.cx)/2),900,yLabel2,FontLabel6,labelsColor); + + if (drawXReticle) + for(int i=0; xMinUnit+i*xMajorUnit<=xRange;i++){ + w.DrawLine(fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit)), + h, + fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit)), + h+scale*4, + fround(scale/2), + axisColor); + Font Standard6; + Standard6.Height(scale*StdFont().GetHeight()); + double gridX=xMinUnit+i*xMajorUnit+xMin; + String gridLabelX; + if (cbModifFormatX) + cbModifFormatX(gridLabelX, i, gridX); + else + gridLabelX = VariableFormatX(gridX); + + Array texts; + Array sizes; + ParseTextMultiline(gridLabelX, StdFont(), texts, sizes); + for (int ii = 0; ii < texts.GetCount(); ++ii) { + int cy = ii == 0 ? 0 : sizes[ii-1].cy; + w.DrawText(fround(l*xMinUnit/xRange+i*l/(xRange/xMajorUnit) - scale*sizes[ii].cx/2), h+scale*(4+ii*cy), texts[ii], Standard6, axisColor); + } + } + if (drawYReticle) + for(int i=0; yMinUnit+i*yMajorUnit<=yRange;i++){ + w.DrawLine(-(scale*4), + fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit)), + 0, + fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit)), + fround(scale/2), + axisColor); + double gridY=yMinUnit+i*yMajorUnit+yMin; + String gridLabelY; + if (cbModifFormatY) + cbModifFormatY(gridLabelY, i, gridY); + else + gridLabelY = VariableFormatY(gridY); + int dx=scale*GetTextSize(gridLabelY,StdFont()).cx; + Font Standard6; + Standard6.Height(scale*StdFont().GetHeight()); + w.DrawText(-dx-scale*6, fround(-h*yMinUnit/yRange+h-i*h/(yRange/yMajorUnit))-scale*8, gridLabelY, Standard6, axisColor); + } + if (drawY2Reticle) + for(int i=0; yMinUnit+i*yMajorUnit<=yRange;i++){ + w.DrawLine(l+(scale*4), + fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit)), + l, + fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit)), + fround(scale/2), + axisColor); + double gridY2=yMinUnit2+i*yMajorUnit2+yMin2; + String gridLabelY2; + if (cbModifFormatY2) + cbModifFormatY2(gridLabelY2, i, gridY2); + else + gridLabelY2 = VariableFormatY2(gridY2); + Font Standard6; + Standard6.Height(scale*StdFont().GetHeight()); + w.DrawText(l+scale*10,fround(-h*yMinUnit2/yRange2+h-i*h/(yRange/yMajorUnit))-scale*8,gridLabelY2,Standard6,axisColor); + } + + if(antialiasing && w.IsGui()) + { + ImageDraw imdraw(3*l,3*h); + Plot (imdraw,3,3*l,3*h); + w.DrawImage(0,0,l,h,imdraw); + } + else Plot(w,scale,l,h); + + w.End(); +} + +Scatter::Scatter(): + title (""), + titleColor(Black), + graphColor(White), + titleFont(Roman(20)), + xLabel(""),yLabel(""), + labelsFont(StdFont()), + labelsColor(Black), + plotAreaColor(::Color(245,245,248)), + axisColor(Black), + axisWidth(6), + px(30), + py(30), + xRange(100.0), + yRange(100.0), + yRange2(100.0), + xMajorUnit(xRange/10), + yMajorUnit(yRange/5), + xMin(0.0), yMin(0.0), yMin2(0.0), + xMinUnit(0.0), yMinUnit(0.0), yMinUnit2(0.0), + logX(false), logY(false), logY2(false), + cbModifFormatX(NULL),cbModifFormatY(NULL),cbModifFormatY2(NULL), + gridColor(::Color(102,102,102)), + gridWidth(4), + paintInfo(false), + mouseHandlingX(false), mouseHandlingY(false), isScrolling(false), isLabelPopUp(false), + drawXReticle(true), drawYReticle(true), drawY2Reticle(false), + drawVGrid(true), drawHGrid(true), + showLegend(true),legendWeight(80), + antialiasing(false), + offset(10,12), + minXZoom(-1), maxXZoom(-1), minYZoom(-1), maxYZoom(-1), fastViewX(false), sequentialXAll(false) +{ + Color(graphColor); + BackPaint(); + popText.SetColor(::Color(200,220,255)); + SetMouseBehavior(defaultMouse); +} + +Scatter::~Scatter() +{ +} +