tag 标签: 分形

相关博文
  • 热度 12
    2016-5-6 10:50
    1256 次阅读|
    1 个评论
    这个程序演示了在STM32F746DISC开发板上显示分形(MandelBrot set),实现了缩放、移动、参数显示等功能。一个手指可以拖动图形,两个手指靠近或分开可以缩放。   此外使用了Guess算法减少计算次数,加快显示速度。       参考代码:   #include "mbed.h" #include "LCD_DISCO_F746NG.h" #include "TS_DISCO_F746NG.h" #include math.h   #define ITERATION  150 #define BAILOUT 4   LCD_DISCO_F746NG lcd; TS_DISCO_F746NG ts; TS_StateTypeDef TS_State; uint8_t ts_nb = 0;   uint16_t tsx0 , tsy0 ; uint16_t tsx , tsy ; uint8_t tscnt = 0; double zoom = 1;   Timer tmr;   uint8_t msg ; uint16_t screen_width, screen_height;   double mx1, my1, mx2, my2;   uint16_t calcMandelBrot(double x, double y) {     uint16_t i;     double xx, yy, tx, ty;          xx = yy = 0;     i = 0;     while((i ITERATION) ((xx*xx + yy*yy) BAILOUT))     {         tx = xx*xx - yy*yy + x;         ty = 2*xx*yy + y;         xx = tx;         yy = ty;         i++;     }     return i; }   uint8_t c ; void rectMandelBrot(double x1, double y1, double x2, double y2) {     double dx, dy;     uint16_t i, j, n;     uint32_t color;        lcd.SetTextColor(LCD_COLOR_BLACK);     lcd.FillRect(0, 0, screen_width, screen_height);     lcd.SetTextColor(LCD_COLOR_WHITE);     sprintf((char *)msg, "%10f", x1);     lcd.DisplayStringAt(screen_width+5, 224, msg, LEFT_MODE);     sprintf((char *)msg, "%10f", y1);     lcd.DisplayStringAt(screen_width+5, 236, msg, LEFT_MODE);     sprintf((char *)msg, "%10f", x2);     lcd.DisplayStringAt(screen_width+5, 248, msg, LEFT_MODE);     sprintf((char *)msg, "%10f", y2);     lcd.DisplayStringAt(screen_width+5, 260, msg, LEFT_MODE);     sprintf((char *)msg, "  %10f", zoom);     lcd.DisplayStringAt(screen_width+5, 212, msg, LEFT_MODE);          tmr.reset();     tmr.start();          dx = (x2 - x1)/screen_width;     dy = (y2 - y1)/screen_height; /*     for(i = 0; i screen_width; i++)     {         for(j = 0; j screen_height; j++)         {             color = calcMandelBrot(x1 + dx*i, y1 + dy*j);             lcd.DrawPixel(i, j, 0xFF000000 | (color14) | (color 4));         }     }*/     for(i = 0; i screen_width/4; i++)     {         ts.GetState(TS_State);         if (TS_State.touchDetected)             return;         for(j = 0; j screen_height/4; j++)         {             c = calcMandelBrot(x1 + 4*dx*i, y1 + 4*dy*j);             lcd.DrawPixel(4*i, 4*j, 0xFF000000 | (c 4));         }     }          for(i = 0; i screen_width/4; i++)     {         ts.GetState(TS_State);         if (TS_State.touchDetected)             return;         for(j = 0; j screen_height/4; j++)         {             if((c == c ) (c == c ) (c == c ))             {                 lcd.SetTextColor(0xFF000000 | (c 4));                 lcd.FillRect(i*4, j*4, 4, 4);                             }             else             {                 for(n = 1; n 16; n++)                 {                     color = calcMandelBrot(x1 + dx*(4*i+(n/4)), y1 + dy*(4*j+(n%4)));                     lcd.DrawPixel(4*i+(n/4), 4*j+(n%4), 0xFF000000 | (color4));                 }             }         }     }       tmr.stop();          sprintf((char *)msg, "  %6d ms", tmr.read_ms());     lcd.SetTextColor(LCD_COLOR_WHITE);     lcd.SetBackColor(LCD_COLOR_BLACK);     lcd.DisplayStringAt(screen_width+5, 20, msg, LEFT_MODE); }   int main() {     uint8_t status;     uint8_t prev_nb_touches = 0;     double cx, cy, lx, ly;       status = ts.Init(lcd.GetXSize(), lcd.GetYSize());      if (status != TS_OK) {         lcd.Clear(LCD_COLOR_RED);         lcd.SetBackColor(LCD_COLOR_RED);         lcd.SetTextColor(LCD_COLOR_WHITE);         lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN INIT FAIL", CENTER_MODE);                  while(1);     }              lcd.Clear(LCD_COLOR_BLACK);     lcd.SetFont(Font12);     lcd.SetTextColor(LCD_COLOR_WHITE);     lcd.SetBackColor(LCD_COLOR_BLACK);       screen_width = lcd.GetXSize() - 120;     screen_height = lcd.GetYSize();       lcd.DisplayStringAt(screen_width+5, 0, (uint8_t *)"Elapsed:", LEFT_MODE);     lcd.DisplayStringAt(screen_width+5, 200, (uint8_t *)"Zoom:", LEFT_MODE);            mx1 = -2.5;     my1 = -2.5;     mx2 = 2.5;     my2 = 2.5;     rectMandelBrot(mx1, my1, mx2, my2);          status = 0;     while(1)     {         wait(0.01);         ts.GetState(TS_State);         if (TS_State.touchDetected)         {             if(TS_State.touchDetected != prev_nb_touches)             {                 status = 0;                 tscnt = 0;                 prev_nb_touches = TS_State.touchDetected;                             }                          if(tscnt 10)             {                 tscnt++;                 if(tscnt == 9)                 {                     ts_nb = TS_State.touchDetected;                     lcd.SetTextColor(LCD_COLOR_BLACK);                     lcd.FillRect(screen_width+5, 60, 120, 48);                 }                 continue;             }                          switch(ts_nb)             {                 case 1:                     if(status == 0)                     {                         status = 1;                         tsx0 = TS_State.touchX ;                         tsy0 = TS_State.touchY ;                     }                     tsx = TS_State.touchX ;                     tsy = TS_State.touchY ;                     lcd.SetTextColor(LCD_COLOR_LIGHTBLUE);                     sprintf((char *)msg, "%3d", TS_State.touchX );                     lcd.DisplayStringAt(screen_width+5, 60, msg, LEFT_MODE);                     sprintf((char *)msg, "%3d", TS_State.touchY );                     lcd.DisplayStringAt(screen_width+5, 72, msg, LEFT_MODE);                     break;                 case 2:                     if(status == 0)                     {                         status = 1;                         tsx0 = TS_State.touchX ;                         tsy0 = TS_State.touchY ;                         tsx0 = TS_State.touchX ;                         tsy0 = TS_State.touchY ;                     }                     tsx = TS_State.touchX ;                     tsy = TS_State.touchY ;                     tsx = TS_State.touchX ;                     tsy = TS_State.touchY ;                     lcd.SetTextColor(LCD_COLOR_LIGHTBLUE);                     sprintf((char *)msg, "%3d", TS_State.touchX );                     lcd.DisplayStringAt(screen_width+5, 60, msg, LEFT_MODE);                     sprintf((char *)msg, "%3d", TS_State.touchY );                     lcd.DisplayStringAt(screen_width+5, 72, msg, LEFT_MODE);                     sprintf((char *)msg, "%3d", TS_State.touchX );                     lcd.DisplayStringAt(screen_width+5, 84, msg, LEFT_MODE);                     sprintf((char *)msg, "%3d", TS_State.touchY );                     lcd.DisplayStringAt(screen_width+5, 96, msg, LEFT_MODE);                     break;             }         }         else         {             if(status)             {                 lcd.SetTextColor(LCD_COLOR_YELLOW);                 status = 0;                 tscnt = 0;                 switch(ts_nb)                 {                     case 1:                         if((abs(tsx - tsx0 ) 20) || (abs(tsy - tsy0 ) 20))                         {                             lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)" - ", LEFT_MODE);                             cx = (tsx - tsx0 )*(mx2 - mx1)/screen_width;                             cy = (tsy - tsy0 )*(my2 - my1)/screen_height;                             mx1 -= cx;                             mx2 -= cx;                             my1 -= cy;                             my2 -= cy;                             rectMandelBrot(mx1, my1, mx2, my2);                         }                         break;                     case 2:                         if(((tsx -tsx )*(tsx -tsx ) + 20) ((tsx0 -tsx0 )*(tsx0 -tsx0 )))                         {                             lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)"out", LEFT_MODE);                             zoom = zoom /2;                             cx = (tsx0 + tsx0 )/2;                             cy = (tsy0 + tsy0 )/2;                             lx = (mx2 - mx1);                             ly = (my2 - my1);                             cx = cx * (mx2 - mx1) / screen_width + mx1;                             cy = cy * (my2 - my1) / screen_height + my1;                             mx1 = cx - lx;                             mx2 = cx + lx;                             my1 = cy - ly;                             my2 = cy + ly;                             rectMandelBrot(mx1, my1, mx2, my2);                                                     }                         else if(((tsx -tsx )*(tsx -tsx )) ((tsx0 -tsx0 )*(tsx0 -tsx0 ) + 20))                         {                             lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)"in ", LEFT_MODE);                             zoom = zoom*2;                             cx = (tsx0 + tsx0 )/2;                             cy = (tsy0 + tsy0 )/2;                             lx = (mx2 - mx1)/4;                             ly = (my2 - my1)/4;                             cx = cx * (mx2 - mx1) / screen_width + mx1;                             cy = cy * (my2 - my1) / screen_height + my1;                             mx1 = cx - lx;                             mx2 = cx + lx;                             my1 = cy - ly;                             my2 = cy + ly;                             rectMandelBrot(mx1, my1, mx2, my2);                                                        }                           break;                 }             }         }         } }     目前已知问题,手势识别还不够灵敏,等待进一步改进。