보간법(Interpolation)
보간법(Interpolation)
--------------------------
두점을 지나는 직선의 방정식과 동일하다.
(x1,y1)-(x2,y2) 두점을 지나는 직선의 방정식
y-y1=(y2-y1)*(x-x1)/(x2-x1)
y=y1+(y2-y1)*(x-x1)/(x2-x1)
*/
inline int interpolation2_x(int x1,int y1,int x2,int y2,int x)//x1~x2좌표값에서 x위치의 값을 계산
{
int y;
y=y1+(y2-y1)*(x-x1)/(x2-x1);
TRACE(_T("%d(%d)~%d(%d) => %d(%d)\r\n"),x1,y1,x2,y2,x,y);
return y;
}
interpolation2_x(0,0,100,100,50);
interpolation2_x(0,0,100,100,0);
interpolation2_x(0,0,100,100,-50);
interpolation2_x(0,0,100,100,100);
interpolation2_x(0,0,100,100,150);
interpolation2_x(0,50,100,100,50);
interpolation2_x(0,50,100,100,0);
interpolation2_x(0,50,100,100,-50);
interpolation2_x(0,50,100,100,100);
interpolation2_x(0,50,100,100,150);
interpolation2_x(0,-100,100,100,50);
interpolation2_x(0,-100,100,100,0);
interpolation2_x(0,-100,100,100,-50);
interpolation2_x(0,-100,100,100,100);
interpolation2_x(0,-100,100,100,150);
0(0)~100(100) => 50(50)
0(0)~100(100) => 0(0)
0(0)~100(100) => -50(-50)
0(0)~100(100) => 100(100)
0(0)~100(100) => 150(150)
0(50)~100(100) => 50(75)
0(50)~100(100) => 0(50)
0(50)~100(100) => -50(25)
0(50)~100(100) => 100(100)
0(50)~100(100) => 150(125)
0(-100)~100(100) => 50(0)
0(-100)~100(100) => 0(-100)
0(-100)~100(100) => -50(-200)
0(-100)~100(100) => 100(100)
0(-100)~100(100) => 150(200)
주용도 : n개의 띄엄띄엄 그래프 좌표 데이터가 있을때, 임의의 위치의 값을 쉽게 계산할 수 있다.
예1) 온도센서를 ADC데이터로 변환한다. -10도, 0도, 10도, 20도, 30도, 40도, 100도, ...
띄엄띄엄 구성된 데이터로도, 비교적 정확한 근사값을 구할 수 있다.
예2) pdf/이미지 파일로된 그래프에서 중요위치의 점 10개를 데이터를 뽑아서, 프로그램상에서 임의의 점의 좌표를 구하여 그래프로 출력한다.
장점 : 적은 수의 데이터로 비교적 정확한 값을 찾을 수 있다.
단점 : 임의의 점이 속한 좌,우 2개의 데이터를 찾아야한다.(약간 복잡)
typedef struct
{
short adc;
float DisplayValue;
}sADC_to_DisplayValue;
sADC_to_DisplayValue sADC_to_DisplayValue_Table[]={
{6632,60},
{6748,54},
{6915,48},
{7072,42},
{7296,36},
{7540,30},
{8711,24},
{10487,18},
{12295,12},
{14023,6},
{24711,0}
};
// 보간법으로 p1,p2를 d1:d2로 분할하는 p를 리턴한다. (단, d1+d2=1)
float lerp(float p1, float p2, float d1)
{
return (1-d1)*p1 + d1*p2;
}
//a,b사이의 점 s_now의 값을 유추. a<s_now,b, fa<bf
float get_point2_value(short a,short s_now,short b,
float fa,float bf)
{
return lerp(fa,bf,((float)s_now-a)/((float)b-a));
}
float ADC_value_to_float(byte1 device0,short adc_value)
{
float f=0.0f;
sADC_to_DisplayValue *t=sADC_to_DisplayValue_Table;
//DEBUG_puts("ADC_value_to_float");
if(adc_value<=t[0].adc)
{
f=t[0].DisplayValue;
}
else if(adc_value>=t[countof(sADC_to_DisplayValue_Table)-1].adc)
{
f=t[countof(sADC_to_DisplayValue_Table)-1].DisplayValue;
}
else
{
int i;
for(i=1;i<countof(sADC_to_DisplayValue_Table);i++)
{
if(adc_value<=t[i].adc)
{
f=get_point2_value(t[i-1].adc,adc_value,t[i].adc,
t[i-1].DisplayValue,t[i].DisplayValue);
break;
}
else
{
}
}
}
return f;
}