카테고리 없음

보간법(Interpolation)

안녕1999 2018. 12. 15. 23:30

보간법(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;

}