ultimatepp/uppsrc/ScatterDraw/Surf.cpp
koldo ce7c5b8740 ScatterDraw: Improved behaviour with Nulls and NaNs
git-svn-id: svn://ultimatepp.org/upp/trunk@15722 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2021-02-01 10:04:40 +00:00

251 lines
No EOL
7.4 KiB
C++

#include "ScatterDraw.h"
namespace Upp {
ScatterDraw& ScatterDraw::AddSurf(DataSourceSurf &_surf) {
surf = &_surf;
if (!IsNum(surfMinZ))
surfMinZ = _surf.MinZ();
if (!IsNum(surfMaxZ))
surfMaxZ = _surf.MaxZ();
return *this;
}
inline static double Smooth01(double val) {
double val2 = val*val;
return 3*val2 - 2*val2*val;
}
inline static double Smooth01Left(double val) {return 2*Smooth01(val/2);}
inline static double Smooth01Right(double val) {return 2*(Smooth01(0.5 + val/2)-0.5);}
inline static double Filter01(double frac) {
if (frac >= 1)
return 1;
else if (frac < 0)
return 0;
return frac;
}
static Color InterpolateColor(double frac, const Color &from, const Color &to) {
return Color(int(from.GetR() + frac*(to.GetR() - from.GetR())),
int(from.GetG() + frac*(to.GetG() - from.GetG())),
int(from.GetB() + frac*(to.GetB() - from.GetB())));
}
Color GetRainbowColor(double frac, RAINBOW rainbow, int numScales) {
frac = Filter01(frac);
switch (rainbow) {
case BLUE_YELLOW_RED: frac = 1 - frac;
return GetRainbowColor(frac, Color(255,0,0), Color(255,255,0), Color(0,0,255), numScales);
case RED_YELLOW_BLUE: return GetRainbowColor(frac, Color(255,0,0), Color(255,255,0), Color(0,0,255), numScales);
case GREEN_YELLOW_RED: frac = 1 - frac;
return GetRainbowColor(frac, Color(255,0,0), Color(255,255,0), Color(0,255,0), numScales);
case RED_YELLOW_GREEN: return GetRainbowColor(frac, Color(255,0,0), Color(255,255,0), Color(0,255,0), numScales);
case WHITE_BLACK: frac = 1 - frac;
return GetRainbowColor(frac, Color(0,0,0), Color(255,255,255), numScales);
case BLACK_WHITE: return GetRainbowColor(frac, Color(0,0,0), Color(255,255,255), numScales);
case BLUE_WHITE_RED: frac = 1 - frac;
return GetRainbowColor(frac, Color(255,0,0), Color(255,255,255), Color(0,0,255), numScales);
case RED_WHITE_BLUE: return GetRainbowColor(frac, Color(255,0,0), Color(255,255,255), Color(0,0,255), numScales);
}
return Null;
}
Color GetRainbowColor(double frac, const Color &from, const Color &to, int numScales) {
if (numScales > 0)
frac = (int(frac*numScales)/double(numScales))/(1 - 1/numScales);
frac = Filter01(frac);
return InterpolateColor(frac, from, to);
}
Color GetRainbowColor(double frac, const Color &col0, const Color &col1, const Color &col2, int numScales) {
if (IsNull(col2))
return GetRainbowColor(frac, col0, col1, numScales);
if (numScales > 0)
frac = int(frac*numScales)/double(numScales - 1);
frac = Filter01(frac);
if (frac < 0.5)
return InterpolateColor((numScales > 0) ? 2*frac : Smooth01Right(2*frac), col0, col1);
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 (!IsNum(z11) || !IsNum(z12) || !IsNum(z21) || !IsNum(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 (!IsNum(z11) || !IsNum(z12) || !IsNum(z21) || !IsNum(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 (!!IsNum(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 (!!IsNum(d)) {
if (ret < d)
ret = d;
}
}
if (ret == DOUBLE_NULL)
return Null;
return ret;
}
}