diff --git a/uppsrc/ScatterDraw/DataSource.cpp b/uppsrc/ScatterDraw/DataSource.cpp index af475fc29..3b573b9aa 100644 --- a/uppsrc/ScatterDraw/DataSource.cpp +++ b/uppsrc/ScatterDraw/DataSource.cpp @@ -661,18 +661,17 @@ bool DataSource::SameX(DataSource &data) { return true; } -void TableData::Init(Vector &data, Vector &xAxis, Vector &yAxis, - Interpolate inter, bool areas) { - ASSERT(areas ? (data.GetCount() == (xAxis.GetCount() - 1)*(yAxis.GetCount() - 1)) : true); - ASSERT(!areas ? (data.GetCount() == xAxis.GetCount()*yAxis.GetCount()) : true); - this->pdata = &data; - this->pxAxis = &xAxis; - this->pyAxis = &yAxis; - this->inter = inter; - this->areas = areas; -} - - +// | | | +// y2--z12------z22- +// | | | +// y---|---o | +// | | | | +// | | | | +// y1--z11-+----z21- +// | | | | +// ----x1--x----x2-- +// +// y11 = y(x1, y1) y12 = y(x1, y2) y21 = y(x2, y1) y22 = y(x2, y2) double BilinearInterpolate(double x, double y, double x1, double x2, double y1, double y2, double z11, double z12, double z21, double z22) { double x_x1 = x - x1; @@ -682,194 +681,6 @@ double BilinearInterpolate(double x, double y, double x1, double x2, double y1, return (z11*x2_x*y2_y + z21*x_x1*y2_y + z12*x2_x*y_y1 + z22*x_x1*y_y1)/(x2 - x1)/(y2 - y1); } -double TableData::z_area(double x, double y) { - if (inter == NO) { - int ix, iy; - for (ix = 0; ix < pxAxis->GetCount(); ++ix) { - if ((*pxAxis)[ix] > x) { - if (ix == 0) - return Null; - else { - ix--; - break; - } - } - } - if (ix == pxAxis->GetCount()) - return Null; - for (iy = 0; iy < pyAxis->GetCount(); ++iy) { - if ((*pyAxis)[iy] > y) { - if (iy == 0) - return Null; - else { - iy--; - break; - } - } - } - if (iy == pyAxis->GetCount()) - return Null; - return (*pdata)[ix + iy*(pxAxis->GetCount() - 1)]; - } else if (inter == BILINEAR) { - int ix, iy; - for (ix = 0; ix < pxAxis->GetCount()-1; ++ix) { - if ((((*pxAxis)[ix]+(*pxAxis)[ix+1])/2.) > x) { - if (ix == 0) - return Null; - else { - ix--; - break; - } - } - } - if (ix == pxAxis->GetCount()-1) - return Null; - for (iy = 0; iy < pyAxis->GetCount()-1; ++iy) { - if ((((*pyAxis)[iy]+(*pyAxis)[iy+1])/2.) > y) { - if (iy == 0) - return Null; - else { - iy--; - break; - } - } - } - if (iy == pyAxis->GetCount()-1) - return Null; - - int width = pxAxis->GetCount() - 1; - double x1 = ((*pxAxis)[ix] + (*pxAxis)[ix+1])/2.; - double x2 = ((*pxAxis)[ix+1] + (*pxAxis)[ix+2])/2.; - double y1 = ((*pyAxis)[iy] + (*pyAxis)[iy+1])/2.; - double y2 = ((*pyAxis)[iy+1] + (*pyAxis)[iy+2])/2.; - double z11 = (*pdata)[ix + iy*width]; - double z12 = (*pdata)[ix + (iy+1)*width]; - double z21 = (*pdata)[ix+1+ iy*width]; - double z22 = (*pdata)[ix+1 + (iy+1)*width]; - if (IsNull(z11) || IsNull(z12) || IsNull(z21) || IsNull(z22)) - return Null; - return BilinearInterpolate(x, y, x1, x2, y1, y2, z11, z12, z21, z22); - } else - return Null; -} - -double TableData::z_point(double x, double y) { - if (x < (*pxAxis)[0] || x > pxAxis->Top() || - y < (*pyAxis)[0] || y > pyAxis->Top()) - return Null; - - if (inter == NO) { - int ix, iy; - if (x < ((*pxAxis)[0] + (*pxAxis)[1])/2.) - ix = 0; - else if (x >= ((*pxAxis)[pxAxis->GetCount()-1] + (*pxAxis)[pxAxis->GetCount()-2])/2.) - ix = pxAxis->GetCount()-1; - else { - for (ix = 1; ix < pxAxis->GetCount()-1; ++ix) { - if (((*pxAxis)[ix] + (*pxAxis)[ix+1])/2. > x) - break; - } - } - if (y < ((*pyAxis)[0] + (*pyAxis)[1])/2.) - iy = 0; - else if (y >= ((*pyAxis)[pyAxis->GetCount()-1] + (*pyAxis)[pyAxis->GetCount()-2])/2.) - iy = pyAxis->GetCount()-1; - else { - for (iy = 1; iy < pyAxis->GetCount()-1; ++iy) { - if (((*pyAxis)[iy] + (*pyAxis)[iy+1])/2. > y) - break; - } - } - return (*pdata)[ix + iy*pxAxis->GetCount()]; - } else if (inter == BILINEAR) { - int ix, iy; - for (ix = 0; ix < pxAxis->GetCount()-1; ++ix) { - if ((*pxAxis)[ix+1] >= x) - break; - } - if (ix == pxAxis->GetCount()-1) - return Null; - for (iy = 0; iy < pyAxis->GetCount()-1; ++iy) { - if ((*pyAxis)[iy+1] >= y) - break; - } - if (iy == pyAxis->GetCount()-1) - return Null; - int width = pxAxis->GetCount(); - double x1 = (*pxAxis)[ix]; - double x2 = (*pxAxis)[ix+1]; - double y1 = (*pyAxis)[iy]; - double y2 = (*pyAxis)[iy+1]; - double z11 = (*pdata)[ix + iy*width]; - double z12 = (*pdata)[ix + (iy+1)*width]; - double z21 = (*pdata)[ix+1 + iy*width]; - double z22 = (*pdata)[ix+1 + (iy+1)*width]; - if (IsNull(z11) || IsNull(z12) || IsNull(z21) || IsNull(z22)) - return Null; - return BilinearInterpolate(x, y, x1, x2, y1, y2, z11, z12, z21, z22); - } else - return Null; -} - -double TableData::z(double x, double y) { - if (areas) - return z_area(x, y); - else - return z_point(x, y); -} - -bool TableData::IsEmpty() { - if (!pdata || !pxAxis || !pyAxis) - return true; - return pdata->IsEmpty() || pxAxis->IsEmpty() || pyAxis->IsEmpty(); -} - -double TableData::MinX() { - return (*pxAxis)[0]; -} - -double TableData::MaxX() { - return pxAxis->Top(); -} - -double TableData::MinY() { - return (*pyAxis)[0]; -} - -double TableData::MaxY() { - return pyAxis->Top(); -} - -double TableData::MinZ() { - Vector &data = *pdata; - double ret = -DOUBLE_NULL; - for (int i = 0; i < data.GetCount(); ++i) { - double &d = data[i]; - if (!IsNull(d)) { - if (ret > d) - ret = d; - } - } - if (ret == -DOUBLE_NULL) - return Null; - return ret; -} - -double TableData::MaxZ() { - Vector &data = *pdata; - double ret = DOUBLE_NULL; - for (int i = 0; i < data.GetCount(); ++i) { - double &d = data[i]; - if (!IsNull(d)) { - if (ret < d) - ret = d; - } - } - if (ret == DOUBLE_NULL) - return Null; - return ret; -} - void ExplicitData::Init(Function funz, double minX, double maxX, double minY, double maxY) { ASSERT(maxX >= minX && maxY >= minY); this->funz = funz; diff --git a/uppsrc/ScatterDraw/DataSource.h b/uppsrc/ScatterDraw/DataSource.h index f933fca5d..b502f9526 100644 --- a/uppsrc/ScatterDraw/DataSource.h +++ b/uppsrc/ScatterDraw/DataSource.h @@ -650,60 +650,132 @@ private: int key; }; -class TableData : public DataSourceSurf { +double BilinearInterpolate(double x, double y, double x1, double x2, double y1, double y2, + double z11, double z12, double z21, double z22); + +class TableInterpolate { public: - enum Interpolate {NO, BILINEAR}; - TableData() : pdata(0), pxAxis(0), pyAxis(0), areas(false) {} - TableData(Vector &data, Vector &xAxis, Vector &yAxis, - Interpolate inter, bool areas) {Init(data, xAxis, yAxis, inter, areas);} - void Init(Vector &data, Vector &xAxis, Vector &yAxis, - Interpolate inter, bool areas); - - double z(double x, double y); + enum Interpolate {NO, BILINEAR}; - bool IsEmpty(); - - double MinX(); - double MaxX(); - double MinY(); - double MaxY(); - double MinZ(); - double MaxZ(); +protected: + Interpolate inter; +}; + + +class TableData : public DataSourceSurf, public TableInterpolate { +public: + typedef double (TableData::*Getdatafun)(int d); + TableData() : areas(false), lendata(0), lenxAxis(0), lenyAxis(0) {}; + Interpolate Inter() {return inter;} void Inter(Interpolate inter) {this->inter = inter;} -private: - Vector *pdata; - Vector *pxAxis; - Vector *pyAxis; - Interpolate inter; + double z_area(Getdatafun getdataX, Getdatafun getdataY, Getdatafun getdata, + double x, double y); + double z_point(Getdatafun getdataX, Getdatafun getdataY, Getdatafun getdata, + double x, double y); + + virtual inline double x(int d) {/*NEVER();*/ return Null;} + virtual inline double y(int d) {/*NEVER();*/ return Null;} + virtual inline double data(int d) {/*NEVER();*/ return Null;} - double z_area(double x, double y); - double z_point(double x, double y); + double z(double x, double y) { + return z(&TableData::x, &TableData::y, &TableData::data, x, y); + } + double z(Getdatafun getdataX, Getdatafun getdataY, Getdatafun getdata, double x, double y) { + if (areas) + return z_area(getdataX, getdataY, getdata, x, y); + else + return z_point(getdataX, getdataY, getdata, x, y); + } + + bool IsEmpty() { + return lendata == 0 || lenxAxis == 0 || lenyAxis == 0; + } + + double MinX(Getdatafun getdata); + virtual double MinX() {return MinX(&TableData::x);} + double MaxX(Getdatafun getdata); + virtual double MaxX() {return MaxX(&TableData::x);} + double MinY(Getdatafun getdata); + virtual double MinY() {return MinY(&TableData::y);} + double MaxY(Getdatafun getdata); + virtual double MaxY() {return MaxY(&TableData::y);} + double MinZ(Getdatafun getdata); + virtual double MinZ() {return MinZ(&TableData::data);} + double MaxZ(Getdatafun getdata); + virtual double MaxZ() {return MaxZ(&TableData::data);} + + int lendata; + int lenxAxis; + int lenyAxis; protected: bool areas; }; -class TableDataAreas : public TableData { +class TableDataVector : public TableData { public: - TableDataAreas() : TableData() {areas = true;} - TableDataAreas(Vector &data, Vector &xAxis, Vector &yAxis, - Interpolate inter) {TableData::Init(data, xAxis, yAxis, inter, true);} + TableDataVector() : pdata(0), pxAxis(0), pyAxis(0) {} + TableDataVector(Vector &data, Vector &xAxis, Vector &yAxis, + Interpolate inter, bool areas) {Init(data, xAxis, yAxis, inter, areas);} void Init(Vector &data, Vector &xAxis, Vector &yAxis, - Interpolate inter) {TableData::Init(data, xAxis, yAxis, inter, true);} + Interpolate inter, bool areas) { + ASSERT(areas ? (data.GetCount() == (xAxis.GetCount() - 1)*(yAxis.GetCount() - 1)) : true); + ASSERT(!areas ? (data.GetCount() == xAxis.GetCount()*yAxis.GetCount()) : true); + this->pdata = &data; + this->lendata = data.GetCount(); + this->pxAxis = &xAxis; + this->lenxAxis = xAxis.GetCount(); + this->pyAxis = &yAxis; + this->lenyAxis = yAxis.GetCount(); + this->inter = inter; + this->areas = areas; + } + virtual inline double x(int id) {return (*pxAxis)[id];} + virtual inline double y(int id) {return (*pyAxis)[id];} + virtual inline double data(int id) {return (*pdata)[id];} + +private: + Vector *pdata; + Vector *pxAxis; + Vector *pyAxis; }; -class TableDataPoints : public TableData { +class TableDataCArray : public TableData { public: - TableDataPoints() : TableData() {areas = false;} - TableDataPoints(Vector &data, Vector &xAxis, Vector &yAxis, - Interpolate inter) {TableData::Init(data, xAxis, yAxis, inter, false);} - void Init(Vector &data, Vector &xAxis, Vector &yAxis, - Interpolate inter) {TableData::Init(data, xAxis, yAxis, inter, false);} + TableDataCArray() : pdata(0), pxAxis(0), pyAxis(0)/*, lendata(-23), lenxAxis(0), lenyAxis(0)*/ {} + TableDataCArray(double *data, int lendata, double *xAxis, int lenxAxis, double *yAxis, int lenyAxis, + Interpolate inter, bool areas) {Init(data, lendata, xAxis, lenxAxis, yAxis, lenyAxis, inter, areas);} + void Init(double *data, int lendata, double *xAxis, int lenxAxis, double *yAxis, int lenyAxis, + Interpolate inter, bool areas) { + ASSERT(areas ? (lendata == (lenxAxis - 1)*(lenyAxis - 1)) : true); + ASSERT(!areas ? (lendata == lenxAxis*lenyAxis) : true); + this->pdata = data; + this->lendata = lendata; + this->pxAxis = xAxis; + this->lenxAxis = lenxAxis; + this->pyAxis = yAxis; + this->lenyAxis = lenyAxis; + this->inter = inter; + this->areas = areas; + } + virtual inline double x(int id) {return pxAxis[id];} + virtual inline double y(int id) {return pyAxis[id];} + virtual inline double data(int id) {return pdata[id];} + +private: + double *pdata; + //int lendata; + double *pxAxis; + //int lenxAxis; + double *pyAxis; + //int lenyAxis; }; + + class ExplicitData : public DataSourceSurf { public: ExplicitData() {} diff --git a/uppsrc/ScatterDraw/DrawingFunctions.cpp b/uppsrc/ScatterDraw/DrawingFunctions.cpp index 368be189c..3b1710c63 100644 --- a/uppsrc/ScatterDraw/DrawingFunctions.cpp +++ b/uppsrc/ScatterDraw/DrawingFunctions.cpp @@ -37,7 +37,7 @@ double GetDashLength(const char *dash) { catch(CParser::Error) {} if (len == 0) len = 100000; - return len; + return len-1; } Vector &GetDashedArray(String dash) { diff --git a/uppsrc/ScatterDraw/Legend.cpp b/uppsrc/ScatterDraw/Legend.cpp index 6dfaace12..597d04d56 100644 --- a/uppsrc/ScatterDraw/Legend.cpp +++ b/uppsrc/ScatterDraw/Legend.cpp @@ -106,11 +106,11 @@ void ScatterDraw::DrawLegend(Draw& w) const { double ly = (rowIncSign >= 0 ? rect.top : rect.bottom) + rowIncSign*int(rowHeight*(row + 0.6) + loclegendRowSpacing*(row + 0.5)); Vector line; - double dashLen = GetDashLength(series[i].dash); + double dashLen = GetDashLength(series[i].dash)*textScale; double realLineLen = lineLen/dashLen > 1 ? dashLen*int(lineLen/dashLen) : lineLen; line << Pointf(lx, ly) << Pointf(lx + realLineLen, ly); if (series[i].opacity > 0 && series[i].seriesPlot) - DrawPolylineOpa(w, line, plotScaleAvg, 1, series[i].thickness, series[i].color, series[i].dash); + DrawPolylineOpa(w, line, textScale, 1, series[i].thickness, series[i].color, series[i].dash); Pointf mark_p(lx + xWidth, ly); if (series[i].markWidth >= 1 && series[i].markPlot) series[i].markPlot->Paint(w, plotScaleAvg, mark_p, series[i].markWidth, series[i].markColor, diff --git a/uppsrc/ScatterDraw/ScatterDraw.cpp b/uppsrc/ScatterDraw/ScatterDraw.cpp index 6d5cc873c..83d435139 100644 --- a/uppsrc/ScatterDraw/ScatterDraw.cpp +++ b/uppsrc/ScatterDraw/ScatterDraw.cpp @@ -251,6 +251,8 @@ void ScatterDraw::AdjustMinUnitY2() { } void ScatterDraw::AdjustMajorUnitX() { + if (xMajorUnit == 0 || IsNull(xMajorUnit)) + return; while (xRange/xMajorUnit > 1.2*xMajorUnitNum) xMajorUnit *= 2; while (xRange/xMajorUnit < xMajorUnitNum/1.5) @@ -258,6 +260,8 @@ void ScatterDraw::AdjustMajorUnitX() { } void ScatterDraw::AdjustMajorUnitY() { + if (yMajorUnit == 0 || IsNull(yMajorUnit)) + return; while (yRange/yMajorUnit > 1.2*yMajorUnitNum) yMajorUnit *= 2; while (yRange/yMajorUnit < yMajorUnitNum/1.5) @@ -265,6 +269,8 @@ void ScatterDraw::AdjustMajorUnitY() { } void ScatterDraw::AdjustMajorUnitY2() { + if (yMajorUnit2 == 0 || IsNull(yMajorUnit2)) + return; while (yRange2/yMajorUnit2 > 1.2*yMajorUnitNum) yMajorUnit2 *= 2; while (yRange2/yMajorUnit2 < yMajorUnitNum/1.5) diff --git a/uppsrc/ScatterDraw/ScatterDraw.h b/uppsrc/ScatterDraw/ScatterDraw.h index aa7e10fd3..b47bfddf1 100644 --- a/uppsrc/ScatterDraw/ScatterDraw.h +++ b/uppsrc/ScatterDraw/ScatterDraw.h @@ -302,10 +302,10 @@ protected: void WhenPaint(Painter &w) {WhenPainter(w);} void WhenPaint(Draw &w) {WhenDraw(w);} +public: template void SetDrawing(T& w, bool ctrl = false); -public: Callback3 cbModifFormatX; Callback3 cbModifFormatXGridUnits; Callback3 cbModifFormatDeltaX; @@ -472,7 +472,7 @@ public: ScatterDraw &AddSeries(Upp::Array &xData, Upp::Array &yData) {return AddSeries(yData, xData);} ScatterDraw &AddSeries(Vector &points) {return AddSeries(points);} - ScatterDraw &AddSeries(Upp::Array &points) {return AddSeries(points);} + ScatterDraw &AddSeries(Upp::Array &points) {return AddSeries(points);} template ScatterDraw &AddSeries(Vector > &data, int idx, int idy, Vector &idsx, Vector &idsy, Vector &idsFixed, bool useCols = true, int beginData = 0, int numData = Null) { @@ -1539,7 +1539,7 @@ void ScatterDraw::Plot(T& w) int npix = 1; for (int64 i = imin; i <= imax; ) { double xx, yy; - if (fastViewX) { + if (fastViewX && dxpix < 1) { yy = series[j].PointsData()->y(i); if (IsNull(yy)) { ++i; diff --git a/uppsrc/ScatterDraw/Surf.cpp b/uppsrc/ScatterDraw/Surf.cpp index 69330c90f..b278eba67 100644 --- a/uppsrc/ScatterDraw/Surf.cpp +++ b/uppsrc/ScatterDraw/Surf.cpp @@ -65,3 +65,180 @@ Color GetRainbowColor(double frac, const Color &col0, const Color &col1, const C else return InterpolateColor((numScales > 0) ? 2*(frac - 0.5) : Smooth01Left(2*(frac - 0.5)), col1, col2); } + +#define Membercall(fun) (this->*fun) + +double TableData::z_area(Getdatafun getdataX, Getdatafun getdataY, Getdatafun getdata, + double x, double y) { + if (inter == NO) { + int ix, iy; + for (ix = 0; ix < lenxAxis; ++ix) { + if (Membercall(getdataX)(ix) > x) { + if (ix == 0) + return Null; + else { + ix--; + break; + } + } + } + if (ix == lenxAxis) + return Null; + for (iy = 0; iy < lenyAxis; ++iy) { + if (Membercall(getdataY)(iy) > y) { + if (iy == 0) + return Null; + else { + iy--; + break; + } + } + } + if (iy == lenyAxis) + return Null; + return Membercall(getdata)(ix + iy*(lenxAxis - 1)); + } else if (inter == BILINEAR) { + int ix, iy; + for (ix = 0; ix < lenxAxis-1; ++ix) { + if (((Membercall(getdataX)(ix)+Membercall(getdataX)(ix+1))/2.) > x) { + if (ix == 0) + return Null; + else { + ix--; + break; + } + } + } + if (ix == lenxAxis-1) + return Null; + for (iy = 0; iy < lenyAxis-1; ++iy) { + if (((Membercall(getdataY)(iy)+Membercall(getdataY)(iy+1))/2.) > y) { + if (iy == 0) + return Null; + else { + iy--; + break; + } + } + } + if (iy == lenyAxis-1) + return Null; + + int width = lenxAxis - 1; + double x1 = (Membercall(getdataX)(ix) + Membercall(getdataX)(ix+1))/2.; + double x2 = (Membercall(getdataX)(ix+1) + Membercall(getdataX)(ix+2))/2.; + double y1 = (Membercall(getdataY)(iy) + Membercall(getdataY)(iy+1))/2.; + double y2 = (Membercall(getdataY)(iy+1) + Membercall(getdataY)(iy+2))/2.; + double z11 = Membercall(getdata)(ix + iy*width); + double z12 = Membercall(getdata)(ix + (iy+1)*width); + double z21 = Membercall(getdata)(ix+1+ iy*width); + double z22 = Membercall(getdata)(ix+1 + (iy+1)*width); + if (IsNull(z11) || IsNull(z12) || IsNull(z21) || IsNull(z22)) + return Null; + return BilinearInterpolate(x, y, x1, x2, y1, y2, z11, z12, z21, z22); + } else + return Null; +} + +double TableData::z_point(Getdatafun getdataX, Getdatafun getdataY, Getdatafun getdata, + double x, double y) { + if (x < MinX(getdataX) || x > MaxX(getdataX) || + y < MinY(getdataY) || y > MaxY(getdataY)) + return Null; + + if (inter == NO) { + int ix, iy; + if (x < (Membercall(getdataX)(0) + Membercall(getdataX)(1))/2.) + ix = 0; + else if (x >= (Membercall(getdata)(lenxAxis-1) + Membercall(getdata)(lenxAxis-2))/2.) + ix = lenxAxis-1; + else { + for (ix = 1; ix < lenxAxis-1; ++ix) { + if ((Membercall(getdataX)(ix) + Membercall(getdataX)(ix+1))/2. > x) + break; + } + } + if (y < (Membercall(getdataY)(0) + Membercall(getdataY)(1))/2.) + iy = 0; + else if (y >= (Membercall(getdataY)(lenyAxis-1) + Membercall(getdataY)(lenyAxis-2))/2.) + iy = lenyAxis-1; + else { + for (iy = 1; iy < lenyAxis-1; ++iy) { + if ((Membercall(getdataY)(iy) + Membercall(getdataY)(iy+1))/2. > y) + break; + } + } + return Membercall(getdata)(ix + iy*lenxAxis); + } else if (inter == BILINEAR) { + int ix, iy; + for (ix = 0; ix < lenxAxis-1; ++ix) { + if (Membercall(getdataX)(ix+1) >= x) + break; + } + if (ix == lenxAxis-1) + return Null; + for (iy = 0; iy < lenyAxis-1; ++iy) { + if (Membercall(getdataY)(iy+1) >= y) + break; + } + if (iy == lenyAxis-1) + return Null; + int width = lenxAxis; + double x1 = Membercall(getdataX)(ix); + double x2 = Membercall(getdataX)(ix+1); + double y1 = Membercall(getdataY)(iy); + double y2 = Membercall(getdataY)(iy+1); + double z11 = Membercall(getdata)(ix + iy*width); + double z12 = Membercall(getdata)(ix + (iy+1)*width); + double z21 = Membercall(getdata)(ix+1 + iy*width); + double z22 = Membercall(getdata)(ix+1 + (iy+1)*width); + if (IsNull(z11) || IsNull(z12) || IsNull(z21) || IsNull(z22)) + return Null; + return BilinearInterpolate(x, y, x1, x2, y1, y2, z11, z12, z21, z22); + } else + return Null; +} + +double TableData::MinX(Getdatafun getdata) { + return Membercall(getdata)(0); +} + +double TableData::MaxX(Getdatafun getdata) { + return Membercall(getdata)(lenxAxis-1); +} + +double TableData::MinY(Getdatafun getdata) { + return Membercall(getdata)(0); +} + +double TableData::MaxY(Getdatafun getdata) { + return Membercall(getdata)(lenyAxis-1); +} + +double TableData::MinZ(Getdatafun getdata) { + double ret = -DOUBLE_NULL; + for (int i = 0; i < lendata; ++i) { + double d = Membercall(getdata)(i); + if (!IsNull(d)) { + if (ret > d) + ret = d; + } + } + if (ret == -DOUBLE_NULL) + return Null; + return ret; +} + +double TableData::MaxZ(Getdatafun getdata) { + double ret = DOUBLE_NULL; + for (int i = 0; i < lendata; ++i) { + double d = Membercall(getdata)(i); + if (!IsNull(d)) { + if (ret < d) + ret = d; + } + } + if (ret == DOUBLE_NULL) + return Null; + return ret; +} \ No newline at end of file