Mandelbrot set generator using DISCO-F746NG.

Dependencies:   BSP_DISCO_F746NG LCD_DISCO_F746NG TS_DISCO_F746NG mbed BUTTON_GROUP

main.cpp

Committer:
MikamiUitOpen
Date:
2016-02-22
Revision:
6:cafbcdf0d166
Parent:
5:d8baac12f595

File content as of revision 6:cafbcdf0d166:

//---------------------------------------------------------------
//  Mandelbrot set generator
//
//  Mandelbrot set is displayed using 3 kinds of color pattern.
//  Tap the Mandelbrot set on the screen, expanded figure by a 
//  factor of two around the tapped position is displayed.
//
//  2016/02/22, Copyright (c) 2016 MIKAMI, Naoki
//---------------------------------------------------------------

#include "button_group.hpp"
#include "mandelbrot.hpp"

using namespace Mikami;

struct PointF
{
    PointF() {}
    PointF(float x0, float y0) : x(x0), y(y0) {}
    float x, y;
};

TS_DISCO_F746NG ts_;
LCD_DISCO_F746NG lcd_;

const int X0_ = 5;      // origin of x axis
const int Y0_ = 5;      // origin of y axis
const int NX_ = 321;    // number of pixels for horizon
const int NY_ = 261;    // number of pixels for vertical

void Redraw(MandelbrotBase *mandel,
            float wH, float hH, PointF xy, int level,
            float &x1, float &x2, float &y1, float &y2)
{
    x1 = xy.x - wH;
    x2 = xy.x + wH;
    y1 = xy.y - hH;
    y2 = xy.y + hH;

    char str[16];
    lcd_.SetTextColor(LCD_COLOR_WHITE);
    sprintf(str, "factor:%6d", 1 << level);
    lcd_.DisplayStringAt(360, 224, (uint8_t *)str, LEFT_MODE);
    sprintf(str, "x:%8.4f", xy.x);
    lcd_.DisplayStringAt(360, 240, (uint8_t *)str, LEFT_MODE);
    sprintf(str, "y:%8.4f", -xy.y);
    lcd_.DisplayStringAt(360, 256, (uint8_t *)str, LEFT_MODE);

    mandel->Display(x1, x2, y1, y2);
}

int main()
{
    const int LEVEL = 18;
    PointF xy[LEVEL];   // corresponding to touched position
    
    uint32_t backColor = 0xFF006A6C;            // teal green
    uint32_t inActive = backColor & 0xE0FFFFFF; // color for inactive button

    // region to be displayed
    float x1 = -2.3f;
    float x2 =  0.9f;
    float y1 = -1.3f;
    float y2 =  1.3f;

    float wH = (x2 - x1)/2.0f;  // half width of region
    float hH = (y2 - y1)/2.0f;  // half height of region
    
    xy[0] = PointF(x1 + wH, y1 + hH);

    lcd_.Clear(backColor);

    MandelbrotBase *mandel[3];
    mandel[0] = new MandelbrotBW(lcd_, X0_, Y0_, NX_, NY_);
    mandel[1] = new MandelbrotColor1(lcd_, X0_, Y0_, NX_, NY_);
    mandel[2] = new MandelbrotColor2(lcd_, X0_, Y0_, NX_, NY_);
    
    const string strButton[3] = {"B & W", "Color1", "Color2"};
    ButtonGroup bGroup(lcd_, ts_, 340, Y0_, 60, 40,
                       LCD_COLOR_BLUE, backColor,
                       3, strButton, 0, 5, 1, Font12);
    Button back(lcd_, ts_, 410, Y0_, 60, 40, LCD_COLOR_BLUE, backColor, "Back", Font12);
    back.Draw(inActive, LCD_COLOR_GRAY);
    

    // area of Mandelbrot set
    Button area(lcd_, ts_, X0_, Y0_, NX_, NY_, backColor, backColor);

    lcd_.SetTextColor(LCD_COLOR_WHITE);
    lcd_.SetFont(&Font20);
    lcd_.DisplayStringAt(60, 130, (uint8_t *)"Mandelbrot set", LEFT_MODE);
    
    int pattern = -1;
    int level = 0;
    bool first = true;
    while (true)
    {
        int num = -1;
        // select color pattern and display
        if (bGroup.GetTouchedNumber(num) && (pattern != num))
        {
            bGroup.Draw(num, LCD_COLOR_DARKBLUE);
            mandel[num]->Display(x1, x2, y1, y2);
            pattern = num;
            bGroup.Redraw(num);

            if (first)
            {
                lcd_.SetBackColor(backColor);
                lcd_.SetFont(&Font12);
                lcd_.DisplayStringAt(350, LINE(15), (uint8_t *)"Tap to zoom in.",
                                     LEFT_MODE);
                first = false;            
            }
        }
        
        // expand twice around tapped point
        if (area.Touched() && (pattern != -1))
        {
            TS_StateTypeDef state = Button::GottenState();

            uint16_t x = state.touchX[0] - X0_;
            uint16_t y = state.touchY[0] - Y0_;
            
            lcd_.SetBackColor(backColor);
            if (++level < LEVEL)
            {
                xy[level] = PointF(mandel[pattern]->Fx(x), mandel[pattern]->Fy(y));
                wH = wH/2.0f;
                hH = hH/2.0f;

                Redraw(mandel[pattern], wH, hH, xy[level], level, x1, x2, y1, y2);
            }
            else
            {
                lcd_.SetFont(&Font20);
                lcd_.DisplayStringAt(X0_+38, 130, (uint8_t *)" No more expand! ",
                                     LEFT_MODE);
                level = LEVEL - 1 ;
            }
            back.Redraw();
        }

        // "Back" button tapped
        if (back.Touched() && level > 0)
        {            
            back.Draw(LCD_COLOR_DARKBLUE);
            lcd_.SetBackColor(backColor);
            if (level > 0)
            {
                level--;
                wH = wH*2.0f;
                hH = hH*2.0f;

                Redraw(mandel[pattern], wH, hH, xy[level], level, x1, x2, y1, y2);
                if (level > 0) back.Redraw();
                else
                    back.Draw(inActive, LCD_COLOR_GRAY);
            }
        }
        wait(0.1f);
    }
}