Created
December 9, 2012 03:51
-
-
Save marionette-of-u/4243255 to your computer and use it in GitHub Desktop.
m_shima2 - draft
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <string> | |
| #include <random> | |
| #include <fstream> | |
| #include <locale> | |
| #include <vector> | |
| #include <memory> | |
| #include <array> | |
| #include <functional> | |
| #include <thread> | |
| #include <mutex> | |
| #include <cstdlib> | |
| #include <boost/preprocessor.hpp> | |
| #include "mpirxx.h" | |
| #include "DxLib.h" | |
| #include "bmp.hpp" | |
| #include "alib.hpp" | |
| #pragma comment(lib, "mpir.lib") | |
| #pragma comment(lib, "mpirxx.lib") | |
| struct set_locale_jp{ | |
| set_locale_jp(){ | |
| setlocale(LC_CTYPE, ""); | |
| std::locale::global(std::locale("japanese")); | |
| } | |
| } set_locale_jp_instance; | |
| namespace const_value{ | |
| enum{ | |
| mandelbrot_width = 512, | |
| mandelbrot_height = 512, | |
| ui_width = mandelbrot_width, | |
| ui_height = 128, | |
| window_width = mandelbrot_width, | |
| window_height = mandelbrot_height + ui_height | |
| }; | |
| } | |
| class input_manager_type{ | |
| public: | |
| input_manager_type(){ | |
| for(int i = 0; i < 0x100; ++i){ | |
| key_buffer[i] = 0; | |
| prev_flag[i] = false; | |
| } | |
| GetMousePoint(&cursor_x[0], &cursor_y[0]); | |
| cursor_x[1] = cursor_x[0]; | |
| cursor_y[1] = cursor_y[0]; | |
| mouse_state = prev_mouse_state = GetMouseInput(); | |
| } | |
| void operator ()(){ | |
| for(int i = 0; i < 0x100; ++i){ | |
| prev_flag[i] = key_buffer[i] == 1 ? true : false; | |
| } | |
| GetHitKeyStateAll(key_buffer); | |
| cursor_x[1] = cursor_x[0]; | |
| cursor_y[1] = cursor_y[0]; | |
| GetMousePoint(&cursor_x[0], &cursor_y[0]); | |
| prev_mouse_state = mouse_state; | |
| mouse_state = GetMouseInput(); | |
| } | |
| int cursor_coord_x() const{ | |
| return cursor_x[0]; | |
| } | |
| int prev_cursor_coord_x() const{ | |
| return cursor_x[1]; | |
| } | |
| int cursor_coord_y() const{ | |
| return cursor_y[0]; | |
| } | |
| int prev_cursor_coord_y() const{ | |
| return cursor_y[1]; | |
| } | |
| bool press(int n) const{ | |
| return key_buffer[n] == 1; | |
| } | |
| bool push(int n) const{ | |
| return key_buffer[n] == 1 && !prev_flag[n]; | |
| } | |
| bool release(int n) const{ | |
| return key_buffer[n] != 1 && prev_flag[n]; | |
| } | |
| bool mouse_press(int n) const{ | |
| return (mouse_state & n) != 0; | |
| } | |
| bool mouse_push(int n) const{ | |
| return (mouse_state & n) != 0 && !((prev_mouse_state & n) != 0); | |
| } | |
| bool mouse_release(int n) const{ | |
| return !((mouse_state & n) != 0) && (prev_mouse_state & n) != 0; | |
| } | |
| private: | |
| char key_buffer[0x100]; | |
| bool prev_flag[0x100]; | |
| int cursor_x[2], cursor_y[2]; | |
| int mouse_state, prev_mouse_state; | |
| } input_manager; | |
| class patter_surface_type{ | |
| public: | |
| void load(){ | |
| pattern_surface = LoadGraph("d/pattern.bmp"); | |
| if(pattern_surface == -1){ | |
| std::abort(); | |
| } | |
| } | |
| int get() const{ | |
| return pattern_surface; | |
| } | |
| private: | |
| int pattern_surface; | |
| } pattern_surface; | |
| namespace pattern{ | |
| class pattern{ | |
| public: | |
| pattern(const patter_surface_type &pattern_surface_, int x_, int y_, int w_, int h_) : | |
| pattern_surface(&pattern_surface_), | |
| x(x_), | |
| y(y_), | |
| w(w_), | |
| h(h_) | |
| {} | |
| void draw(int dest_x, int dest_y) const{ | |
| DrawRectGraph(dest_x, dest_y, x, y, w, h, pattern_surface->get(), FALSE, FALSE); | |
| } | |
| private: | |
| pattern(){} | |
| const patter_surface_type *pattern_surface; | |
| int x, y, w, h; | |
| }; | |
| pattern gimg_zero(pattern_surface, 0, 0, 16, 16); | |
| #define WRITE(z, i, nil) \ | |
| pattern \ | |
| gimg_ ## i(pattern_surface, 16 + i * 16, 0, 16, 16); | |
| BOOST_PP_REPEAT(4, WRITE, nil); | |
| #undef WRITE | |
| pattern *gimg[4] = { | |
| #define WRITE(z, i, nil) BOOST_PP_COMMA_IF(i) &gimg_ ## i | |
| BOOST_PP_REPEAT(4, WRITE, nil) | |
| #undef WRITE | |
| }; | |
| #define WRITE(z, i, nil) \ | |
| pattern \ | |
| num_ ## i(pattern_surface, 0 + i * 5, 48, 5, 7); | |
| BOOST_PP_REPEAT(10, WRITE, nil); | |
| #undef WRITE | |
| pattern *num[10] = { | |
| #define WRITE(z, i, nil) BOOST_PP_COMMA_IF(i) &num_ ## i | |
| BOOST_PP_REPEAT(10, WRITE, nil) | |
| #undef WRITE | |
| }; | |
| pattern | |
| num_dot(pattern_surface, 50, 48, 5, 7), | |
| num_plus(pattern_surface, 50 + 5, 48, 5, 7), | |
| num_minus(pattern_surface, 50 + 5 * 2, 48, 5, 7), | |
| char_x(pattern_surface, 0, 56, 4, 6), | |
| char_y(pattern_surface, 4, 56, 4, 6), | |
| char_hyphen(pattern_surface, 8, 56, 4, 6), | |
| str_valueislimit(pattern_surface, 0, 62, 129, 7), | |
| str_failed(pattern_surface, 0, 69, 18, 7), | |
| str_sin(pattern_surface, 0, 76, 20, 7), | |
| str_cos(pattern_surface, 20, 76, 20, 7), | |
| str_tan(pattern_surface, 40, 76, 20, 7); | |
| } | |
| std::string make_filename(std::string ext){ | |
| std::time_t time = std::time(nullptr); | |
| std::tm *tm = std::localtime(&time); | |
| char path[0x100]; | |
| std::sprintf( | |
| path, | |
| "%04d_%02d_%02d_%02d_%02d_%02d.%s", | |
| tm->tm_year + 1900, | |
| tm->tm_mon + 1, | |
| tm->tm_mday, | |
| tm->tm_hour, | |
| tm->tm_min, | |
| tm->tm_sec, | |
| ext.c_str() | |
| ); | |
| return path; | |
| } | |
| struct plain_thread_data_draw{ | |
| int fn_pattern_r, fn_pattern_g, fn_pattern_b; | |
| unsigned int rad_a, rad_b, rad_c; | |
| plain_thread_data_draw() : | |
| fn_pattern_r(0), fn_pattern_g(0), fn_pattern_b(0), | |
| rad_a(0), rad_b(0), rad_c(0) | |
| {} | |
| bool operator ==(const plain_thread_data_draw &other) const{ | |
| return | |
| fn_pattern_r == other.fn_pattern_r && | |
| fn_pattern_g == other.fn_pattern_g && | |
| fn_pattern_b == other.fn_pattern_b && | |
| rad_a == other.rad_a && | |
| rad_b == other.rad_b && | |
| rad_c == other.rad_c; | |
| } | |
| bool operator !=(const plain_thread_data_draw &other) const{ | |
| return !(*this == other); | |
| } | |
| }; | |
| struct thread_data_draw : plain_thread_data_draw{ | |
| mpf_class xmin, xmax, ymin, ymax; | |
| thread_data_draw() : plain_thread_data_draw(), xmin(), xmax(), ymin(), ymax(){} | |
| thread_data_draw &operator =(const thread_data_draw &other){ | |
| #define ASSIGN(a) a.set_prec(other.a.get_prec()), a = other.a | |
| ASSIGN(xmin), ASSIGN(xmax), ASSIGN(ymin), ASSIGN(ymax); | |
| #undef ASSIGN | |
| static_cast<plain_thread_data_draw&>(*this) = static_cast<const plain_thread_data_draw&>(other); | |
| return *this; | |
| } | |
| bool operator ==(const thread_data_draw &other) const{ | |
| return | |
| (static_cast<const plain_thread_data_draw&>(*this) == static_cast<const plain_thread_data_draw&>(other)) && | |
| xmin == other.xmin && | |
| xmax == other.xmax && | |
| ymin == other.ymin && | |
| ymax == other.ymax; | |
| } | |
| bool operator !=(const thread_data_draw &other) const{ | |
| return !(*this == other); | |
| } | |
| void save() const{ | |
| std::ofstream ofile(make_filename("txt").c_str()); | |
| if(ofile.fail()){ std::abort(); } | |
| mp_exp_t e = 1; | |
| #define OUT_F(a) ofile << a.get_prec() << "\n" << a.get_str(e) << "\n"; ofile << e << "\n" | |
| OUT_F(xmin), OUT_F(xmax), OUT_F(ymin), OUT_F(ymax); | |
| #undef OUT_F | |
| #define OUT_F(a) ofile << a << "\n" | |
| OUT_F(fn_pattern_r), OUT_F(fn_pattern_g), OUT_F(fn_pattern_b); | |
| OUT_F(rad_a), OUT_F(rad_b), OUT_F(rad_c); | |
| #undef OUT_F | |
| } | |
| void load(){ | |
| std::ifstream ifile("read.txt"); | |
| if(ifile.fail()){ std::abort(); } | |
| std::string str; | |
| mp_exp_t e; | |
| unsigned int q; | |
| #define READ_MPF(a) READ_F(q); a.set_prec(q); READ_F(str); READ_F(e); a.set_str(str, 10) | |
| #define READ_F(a) ifile >> a; if(ifile.fail()){ goto err; } | |
| READ_MPF(xmin), READ_MPF(xmax), READ_MPF(ymin), READ_MPF(ymax); | |
| READ_F(fn_pattern_r); | |
| READ_F(fn_pattern_g); | |
| READ_F(fn_pattern_b); | |
| READ_F(rad_a); | |
| READ_F(rad_b); | |
| READ_F(rad_c); | |
| #undef READ_F | |
| #undef READ_MPF | |
| return; | |
| err:; | |
| std::ofstream ofile("error.txt"); | |
| if(ofile.fail()){ std::abort(); } | |
| ofile << "read.txtの読み込みに失敗\n"; | |
| #define SET_X(a, b) a.set_prec(64), a.set_str(b, 10) | |
| SET_X(xmin, "-2"), SET_X(xmax, "2"), SET_X(ymin, "-2"), SET_X(ymax, "2"); | |
| #undef SET_X | |
| rad_c = rad_b = rad_a = 0; | |
| } | |
| }; | |
| class mpf_prec_ctrl{ | |
| public: | |
| static mp_bitcnt_t get(){ | |
| return value(); | |
| } | |
| static void set(){ | |
| mpf_set_default_prec(value()); | |
| } | |
| static void set(mp_bitcnt_t v){ | |
| value() = v; | |
| mpf_set_default_prec(v); | |
| } | |
| static void set(mp_bitcnt_t v, thread_data_draw &ref){ | |
| set(v); | |
| mpf_class a(0, v); | |
| a = ref.xmin; | |
| ref.xmin.set_prec(v); | |
| ref.xmin = a; | |
| a = ref.xmax; | |
| ref.xmax.set_prec(v); | |
| ref.xmax = a; | |
| a = ref.ymin; | |
| ref.ymin.set_prec(v); | |
| ref.ymin = a; | |
| a = ref.ymax; | |
| ref.ymax.set_prec(v); | |
| ref.ymax = a; | |
| } | |
| private: | |
| static mp_bitcnt_t &value(){ | |
| static mp_bitcnt_t v = 64; | |
| return v; | |
| } | |
| }; | |
| typedef std::array<unsigned char, 3> rgb_type; | |
| typedef tty::alib<>::trigonometric_function<16> tf_type; | |
| tf_type tf; | |
| struct common_data{ | |
| std::function<void(int, int, int, rgb_type)> set_pixel; | |
| std::pair<int, int> size; | |
| std::pair<int, int> height_begin_end; | |
| }; | |
| volatile bool exit_flag = false; | |
| const unsigned int thread_num = std::thread::hardware_concurrency(); | |
| std::unique_ptr<bool[]> generate_flags(new bool[thread_num]); | |
| std::unique_ptr<common_data[]> common_data_array(new common_data[thread_num]); | |
| bool test_all_generate_flags(){ | |
| for(unsigned int i = 0; i < thread_num; ++i){ | |
| if(generate_flags[i]){ return true; } | |
| } | |
| return false; | |
| } | |
| void set_all_generate_flags(bool a){ | |
| for(unsigned int i = 0; i < thread_num; ++i){ | |
| generate_flags[i] = a; | |
| } | |
| } | |
| struct init_flag{ | |
| init_flag(){ | |
| for(unsigned int i = 0; i < thread_num; ++i){ | |
| generate_flags[i] = false; | |
| } | |
| } | |
| } init_flag_instance; | |
| class mandelbrot{ | |
| public: | |
| static const int maxiter = 0x100; | |
| mandelbrot() : | |
| bmp(nullptr), | |
| thread_array(new std::thread[thread_num]), | |
| color_plt(new rgb_type[maxiter]) | |
| { | |
| data.xmin = -2.0, data.xmax = 2.0; | |
| data.ymin = -2.0, data.ymax = 2.0; | |
| data.fn_pattern_r = data.fn_pattern_g = data.fn_pattern_b = 0; | |
| data.rad_a = data.rad_b = data.rad_c = 0; | |
| } | |
| inline static rgb_type rgb(unsigned char r, unsigned char g, unsigned char b){ | |
| rgb_type a; | |
| a[0] = r, a[1] = g, a[2] = b; | |
| return a; | |
| } | |
| private: | |
| struct function_pattern{ | |
| enum{ sin = 0, cos = 1, tan = 2 }; | |
| typedef void (*draw_fn_type)(rgb_type *color, int maxiter, unsigned int rad_a, unsigned int rad_b, unsigned int rad_c, tf_type &tf); | |
| struct draw_fn{ | |
| #include "draw_fn.hpp" | |
| }; | |
| static draw_fn_type draw_dispatch(int r, int g, int b){ | |
| static draw_fn_type fn_array[3 * 3 * 3] = { | |
| #include "draw_fn_enum.hpp" | |
| }; | |
| return fn_array[r + g * 3 + b * 3 * 3]; | |
| } | |
| }; | |
| public: | |
| void make_color_plt(const thread_data_draw &data){ | |
| if(this->data != data){ | |
| rgb_type *const color = &color_plt[0]; | |
| color_plt[0][0] = color_plt[0][1] = 0, color_plt[0][2] = 0; | |
| function_pattern::draw_dispatch(data.fn_pattern_r, data.fn_pattern_g, data.fn_pattern_b) | |
| (&color_plt[0], maxiter, data.rad_a, data.rad_b, data.rad_c, tf); | |
| this->data = data; | |
| } | |
| } | |
| void make( | |
| const int thread_idx, | |
| const common_data &common, | |
| const thread_data_draw &data | |
| ){ | |
| const int | |
| width = common.size.first, | |
| height = common.size.second, | |
| height_begin = common.height_begin_end.first, | |
| height_end = common.height_begin_end.second; | |
| mpf_class dx = data.xmax - data.xmin, dy = data.ymax - data.ymin; | |
| if(dx == 0 || dy == 0){ | |
| generate_flags[thread_idx] = false; | |
| return; | |
| } | |
| int i_max = width, j_max = height_end; | |
| std::unique_ptr<int[]> interrupt_array(new int[thread_num]); | |
| auto recursive_launch_other_thread = [&](const int y, const int end){ | |
| int n = 0; | |
| mutex_make_rec_thread.lock(); | |
| for(unsigned int i = 0; i < thread_num; ++i){ | |
| if(i == thread_idx || thread_array[i].joinable()){ | |
| continue; | |
| } | |
| interrupt_array[n++] = i; | |
| } | |
| if(n == 0){ | |
| mutex_make_rec_thread.unlock(); | |
| return end; | |
| } | |
| int m = end - y; | |
| if(m >= n){ | |
| for(int i = 0; i < n - 1; ++i){ | |
| int idx = interrupt_array[i]; | |
| generate_flags[idx] = true; | |
| common_data_array[idx].set_pixel = common.set_pixel; | |
| common_data_array[idx].size = common.size; | |
| common_data_array[idx].height_begin_end.first = y + (i + 1) * m / (n + 1); | |
| common_data_array[idx].height_begin_end.second = y + (i + 2) * m / (n + 1); | |
| thread_array[idx] = std::thread(&mandelbrot::make, std::ref(*this), idx, std::ref(common_data_array[idx]), std::ref(data)); | |
| } | |
| int idx = interrupt_array[n - 1]; | |
| generate_flags[idx] = true; | |
| common_data_array[idx].set_pixel = common.set_pixel; | |
| common_data_array[idx].size = common.size; | |
| common_data_array[idx].height_begin_end.first = (y + 1) + m / (n + 1); | |
| common_data_array[idx].height_begin_end.second = end; | |
| thread_array[idx] = std::thread(&mandelbrot::make, std::ref(*this), idx, std::ref(common_data_array[idx]), std::ref(data)); | |
| mutex_make_rec_thread.unlock(); | |
| return y + m / (n + 1); | |
| }else{ | |
| mutex_make_rec_thread.unlock(); | |
| return end; | |
| } | |
| }; | |
| mpf_class x, y, a, b, a2, b2; | |
| dx /= width, dy /= height; | |
| const mpf_class two = 2, four = 4; | |
| for(int j = height_begin; j <= j_max; ++j){ | |
| j_max = recursive_launch_other_thread(j, j_max); | |
| for(int i = 0; i <= i_max; ++i){ | |
| x = data.xmin + i * dx; | |
| // y = ymax - j * dy; | |
| y = dy; | |
| y *= -j; | |
| y += data.ymax; | |
| a = x, b = y; | |
| // a2 = a * a; | |
| a2 = a; | |
| a2 *= a; | |
| // b2 = b * b; | |
| b2 = b; | |
| b2 *= b; | |
| int count = maxiter - 1; | |
| while(count != 0 && (a2 + b2) <= four){ | |
| // b = 2 * a * b - y; | |
| b *= two; | |
| b *= a; | |
| b -= y; | |
| // a = a2 - b2 - x; | |
| a = a2; | |
| a -= b2; | |
| a -= x; | |
| // a2 = a * a; | |
| a2 = a; | |
| a2 *= a; | |
| // b2 = b * b | |
| b2 = b; | |
| b2 *= b; | |
| --count; | |
| } | |
| if(exit_flag){ | |
| return; | |
| } | |
| if(!(i / width || j / height)){ | |
| common.set_pixel((width - i - 1), j, count, color_plt[count]); | |
| }else{ break; } | |
| } | |
| } | |
| generate_flags[thread_idx] = false; | |
| } | |
| thread_data_draw data; | |
| tty::bmp *bmp; | |
| std::unique_ptr<std::thread[]> thread_array; | |
| std::thread bmp_thread; | |
| std::unique_ptr<rgb_type[]> color_plt; | |
| std::mutex mutex_make_rec_thread; | |
| private: | |
| mandelbrot(const mandelbrot&){} | |
| } mandelbrot_instance; | |
| struct ui{ | |
| enum mode_enum{ | |
| mode_title, | |
| mode_mandelbrot | |
| }; | |
| enum message_enum{ | |
| message_n, | |
| message_value_is_limit, | |
| message_failed | |
| }; | |
| enum dad_enum{ | |
| dad_off, | |
| dad_on, | |
| dad_lock, | |
| dad_drop | |
| }; | |
| ui() : | |
| draw_pixel(), | |
| gcount(0), | |
| buffer_handle(MakeXRGB8ColorSoftImage(const_value::mandelbrot_width, const_value::mandelbrot_height)), | |
| mode(mode_title), | |
| message(message_n), | |
| dad(dad_off), | |
| cache_array() | |
| { | |
| if(buffer_handle == -1){ | |
| std::abort(); | |
| } | |
| draw_pixel = [&](int x, int y, int pltidx, rgb_type c){ | |
| DrawPixelSoftImage_Unsafe_XRGB8(buffer_handle, x, y, c[0], c[1], c[2]); | |
| }; | |
| current_data.xmin = -2.0, current_data.xmax = 2.0; | |
| current_data.ymin = -2.0, current_data.ymax = 2.0; | |
| } | |
| bool next_mandelbrot(const thread_data_draw &data){ | |
| if(test_all_generate_flags()){ return false; } | |
| join_all_thread(); | |
| cache_array.push_back(data); | |
| current_data = data; | |
| mandelbrot_instance.make_color_plt(current_data); | |
| launch_draw_thread(draw_pixel, const_value::mandelbrot_width, const_value::mandelbrot_height, current_data); | |
| return true; | |
| } | |
| bool prev_mandelbrot(){ | |
| if(test_all_generate_flags() || cache_array.size() <= 1){ return false; } | |
| join_all_thread(); | |
| cache_array.pop_back(); | |
| current_data = cache_array.back(); | |
| mandelbrot_instance.make_color_plt(current_data); | |
| launch_draw_thread(draw_pixel, const_value::mandelbrot_width, const_value::mandelbrot_height, current_data); | |
| return true; | |
| } | |
| bool put_mandelbrot(const thread_data_draw &data, double p){ | |
| if(test_all_generate_flags() || p <= (1.0 / 512.0) || p >= (4194304.0 - 1.0)){ return false; } | |
| current_data = data; | |
| try{ | |
| if(mandelbrot_instance.bmp_thread.joinable()){ | |
| mandelbrot_instance.bmp_thread.join(); | |
| } | |
| std::thread t( | |
| [&](){ | |
| int width = static_cast<int>(const_value::mandelbrot_width * p), height = static_cast<int>(const_value::mandelbrot_height * p); | |
| join_all_thread(); | |
| mandelbrot_instance.make_color_plt(current_data); | |
| mandelbrot_instance.bmp = new tty::bmp(tty::bmp::ColorNum::n256, width, height); | |
| tty::bmp &bmp(*mandelbrot_instance.bmp); | |
| for(int i = 0xFF; i > 0; --i){ | |
| rgb_type a = mandelbrot_instance.color_plt[i]; | |
| bmp.setplt(i, tty::bmp::rgb(a[0], a[1], a[2])); | |
| } | |
| set_all_generate_flags(true); | |
| launch_draw_thread( | |
| [&](int x, int y, int pltidx, rgb_type c){ | |
| bmp.pltidx(x, y, pltidx); | |
| }, | |
| width, | |
| height, | |
| current_data | |
| ); | |
| join_generate_thread(); | |
| bmp.write(make_filename("bmp").c_str()); | |
| delete mandelbrot_instance.bmp; | |
| mandelbrot_instance.bmp = nullptr; | |
| } | |
| ); | |
| mandelbrot_instance.bmp_thread.swap(t); | |
| }catch(std::domain_error e){ | |
| return false; | |
| } | |
| return true; | |
| } | |
| void proc(){ | |
| if(input_manager.mouse_press(MOUSE_INPUT_LEFT) || input_manager.mouse_press(MOUSE_INPUT_RIGHT)){ | |
| if( | |
| mode != mode_title && | |
| dad == dad_off && | |
| input_manager.cursor_coord_x() >= 0 && | |
| input_manager.cursor_coord_x() < const_value::mandelbrot_width && | |
| input_manager.cursor_coord_y() >= 0 && | |
| input_manager.cursor_coord_y() < const_value::mandelbrot_height | |
| ){ dad = dad_on; } | |
| const int offset_y = const_value::mandelbrot_height + 39 + 9 * 5 + 20 - 6; | |
| const unsigned int rad = input_manager.cursor_coord_x(); | |
| if(input_manager.cursor_coord_y() >= offset_y && input_manager.cursor_coord_y() <= offset_y + 6){ | |
| current_data.rad_a = rad; | |
| }else if(input_manager.cursor_coord_y() >= offset_y + 6 && input_manager.cursor_coord_y() <= offset_y + 12){ | |
| current_data.rad_b = rad; | |
| }else if(input_manager.cursor_coord_y() >= offset_y + 12 && input_manager.cursor_coord_y() <= offset_y + 18){ | |
| current_data.rad_c = rad; | |
| } | |
| } | |
| if(test_all_generate_flags()){ | |
| ++gcount; | |
| }else{ | |
| if(mode == mode_mandelbrot){ | |
| if(input_manager.push(KEY_INPUT_A)){ | |
| mode = mode_mandelbrot; | |
| message = message_n; | |
| current_data.xmin = -2.0, current_data.xmax = 2; | |
| current_data.ymin = -2.0, current_data.ymax = 2; | |
| if(!next_mandelbrot(current_data)){ | |
| message = message_failed; | |
| } | |
| }else if(input_manager.push(KEY_INPUT_F)){ | |
| cache_array.clear(); | |
| }else if(input_manager.push(KEY_INPUT_S)){ | |
| current_data.save(); | |
| }else if(input_manager.push(KEY_INPUT_D)){ | |
| current_data.load(); | |
| }else if(input_manager.push(KEY_INPUT_Z)){ | |
| if(!next_mandelbrot(current_data)){ | |
| message = message_failed; | |
| } | |
| }else if(input_manager.push(KEY_INPUT_X)){ | |
| if(!prev_mandelbrot()){ | |
| message = message_failed; | |
| } | |
| }else if(input_manager.push(KEY_INPUT_B)){ | |
| if(!put_mandelbrot(current_data, 1.0)){ | |
| message = message_failed; | |
| } | |
| } | |
| switch(dad){ | |
| case dad_on: | |
| dad_x_begin = input_manager.cursor_coord_x(); | |
| if(dad_x_begin < 0){ | |
| dad_x_begin = 0; | |
| }else if(dad_x_begin >= const_value::mandelbrot_width){ | |
| dad_x_begin = const_value::mandelbrot_width - 1; | |
| } | |
| dad_y_begin = input_manager.cursor_coord_y(); | |
| if(dad_y_begin < 0){ | |
| dad_y_begin = 0; | |
| }else if(dad_y_begin >= const_value::mandelbrot_height){ | |
| dad_y_begin = const_value::mandelbrot_height - 1; | |
| } | |
| dad = dad_lock; | |
| break; | |
| case dad_drop: | |
| { | |
| int cursor_x = input_manager.cursor_coord_x(), cursor_y = input_manager.cursor_coord_y(); | |
| if(cursor_x < 0){ | |
| cursor_x = 0; | |
| }else if(cursor_x >= const_value::mandelbrot_width){ | |
| cursor_x = const_value::mandelbrot_width - 1; | |
| } | |
| if(cursor_y < 0){ | |
| cursor_y = 0; | |
| }else if(cursor_y >= const_value::mandelbrot_height){ | |
| cursor_y = const_value::mandelbrot_height - 1; | |
| } | |
| if(dad_x_begin == cursor_x || dad_y_begin == cursor_y){ | |
| break; | |
| } | |
| dad = dad_off; | |
| int tx, ty, coex, coey; | |
| if(dad_x_begin < cursor_x){ | |
| coex = 1; | |
| tx = cursor_x - dad_x_begin; | |
| }else{ | |
| coex = -1; | |
| tx = dad_x_begin - cursor_x; | |
| } | |
| if(dad_y_begin < cursor_y){ | |
| coey = 1; | |
| ty = cursor_y - dad_y_begin; | |
| }else{ | |
| coey = -1; | |
| ty = dad_y_begin - cursor_y; | |
| } | |
| int m = tx < ty ? tx : ty; | |
| dad_x_end = dad_x_begin + m * coex; | |
| dad_y_end = dad_y_begin + m * coey; | |
| if(dad_x_begin > dad_x_end){ | |
| std::swap(dad_x_begin, dad_x_end); | |
| } | |
| dad_y_begin -= const_value::mandelbrot_height / 2; | |
| dad_y_end -= const_value::mandelbrot_height / 2; | |
| dad_y_begin *= -1; | |
| dad_y_end *= -1; | |
| dad_y_begin += const_value::mandelbrot_height / 2; | |
| dad_y_end += const_value::mandelbrot_height / 2; | |
| if(dad_y_begin > dad_y_end){ | |
| std::swap(dad_y_begin, dad_y_end); | |
| } | |
| tx = dad_x_end - dad_x_begin, ty = dad_y_end - dad_y_begin; | |
| int length = length = tx < ty ? tx : ty; | |
| { | |
| mpf_class | |
| quantity_x = (current_data.xmax - current_data.xmin) / const_value::mandelbrot_width, | |
| quantity_y = (current_data.ymax - current_data.ymin) / const_value::mandelbrot_height; | |
| current_data.xmin = current_data.xmin + dad_x_begin * quantity_x; | |
| current_data.xmax = current_data.xmin + length * quantity_x; | |
| current_data.ymin = current_data.ymin + dad_y_begin * quantity_y; | |
| current_data.ymax = current_data.ymin + length * quantity_y; | |
| } | |
| if(next_mandelbrot(current_data)){ | |
| message = message_n; | |
| }else{ | |
| message = message_failed; | |
| } | |
| } | |
| break; | |
| } | |
| }else{ | |
| if(input_manager.push(KEY_INPUT_Z)){ | |
| mode = mode_mandelbrot; | |
| current_data.xmin = -2.0, current_data.xmax = 2.0; | |
| current_data.ymin = -2.0, current_data.ymax = 2.0; | |
| next_mandelbrot(current_data); | |
| message = message_n; | |
| } | |
| } | |
| } | |
| } | |
| void draw() const{ | |
| auto draw_colorbar = [&](int ur, int ug, int ub){ | |
| const int offset_y = const_value::mandelbrot_height + 39 + 9 * 5 + 20; | |
| int ar[] = { ur, ug, ub }; | |
| for(int i = 0; i < 3; ++i){ | |
| int y = offset_y + 6 * i - 3; | |
| DrawLine(0, y, const_value::ui_width, y, GetColor(0x00, 0x00, 0x00)); | |
| DrawLine(ar[i], y - 3, ar[i], y + 3, GetColor(0xFF, 0x00, 0x00)); | |
| } | |
| }; | |
| DrawBox(0, 0, const_value::window_width, const_value::window_height, GetColor(0xFF, 0xFF, 0xFF), TRUE); | |
| pattern::char_x.draw(2, const_value::mandelbrot_height + 2); | |
| draw_int(2, const_value::mandelbrot_height + 9, static_cast<int>(current_data.xmin.get_prec())); | |
| pattern::char_y.draw(2, const_value::mandelbrot_height + 40); | |
| draw_int(2, const_value::mandelbrot_height + 39 + 9, static_cast<int>(current_data.ymin.get_prec())); | |
| draw_fn( | |
| 2, | |
| const_value::mandelbrot_height + 39 + 9 * 4, | |
| current_data.fn_pattern_r, | |
| current_data.fn_pattern_g, | |
| current_data.fn_pattern_b | |
| ); | |
| draw_colorbar(current_data.rad_a, current_data.rad_b, current_data.rad_c); | |
| for(int i = 0; i < 8; ++i){ | |
| pattern::char_hyphen.draw(6 + 4 * i, const_value::mandelbrot_height + 2); | |
| pattern::char_hyphen.draw(6 + 4 * i, const_value::mandelbrot_height + 40); | |
| } | |
| if(test_all_generate_flags()){ | |
| pattern::gimg[(gcount / 4) % 4]->draw(const_value::ui_width - 16, const_value::mandelbrot_height); | |
| }else{ | |
| if(dad == dad_lock){ | |
| int cursor_x = input_manager.cursor_coord_x(), cursor_y = input_manager.cursor_coord_y(); | |
| if(cursor_x < 0){ | |
| cursor_x = 0; | |
| }else if(cursor_x >= const_value::mandelbrot_width){ | |
| cursor_x = const_value::mandelbrot_width - 1; | |
| } | |
| if(cursor_y < 0){ | |
| cursor_y = 0; | |
| }else if(cursor_y >= const_value::mandelbrot_height){ | |
| cursor_y = const_value::mandelbrot_height - 1; | |
| } | |
| int tx, ty, coex, coey; | |
| if(dad_x_begin < cursor_x){ | |
| coex = 1; | |
| tx = cursor_x - dad_x_begin; | |
| }else{ | |
| coex = -1; | |
| tx = dad_x_begin - cursor_x; | |
| } | |
| if(dad_y_begin < cursor_y){ | |
| coey = 1; | |
| ty = cursor_y - dad_y_begin; | |
| }else{ | |
| coey = -1; | |
| ty = dad_y_begin - cursor_y; | |
| } | |
| int m = (std::min)(tx, ty); | |
| DWORD red = GetColor(0xFF, 0x00, 0x00); | |
| DrawLine(dad_x_begin, dad_y_begin, dad_x_begin + m * coex, dad_y_begin, red); | |
| DrawLine(dad_x_begin, dad_y_begin + m * coey, dad_x_begin + m * coex + (coex >= 0 ? 1 : -1), dad_y_begin + m * coey, red); | |
| DrawLine(dad_x_begin, dad_y_begin, dad_x_begin, dad_y_begin + m * coey, red); | |
| DrawLine(dad_x_begin + m * coex, dad_y_begin, dad_x_begin + m * coex, dad_y_begin + m * coey, red); | |
| DrawLine(dad_x_begin, dad_y_begin, cursor_x, cursor_y, red); | |
| } | |
| pattern::gimg_zero.draw(const_value::ui_width - 16, const_value::mandelbrot_height); | |
| } | |
| static const int message_x = 2, message_y = const_value::mandelbrot_height + 100; | |
| switch(message){ | |
| case message_value_is_limit: | |
| pattern::str_valueislimit.draw(message_x, message_y); | |
| break; | |
| case message_failed: | |
| pattern::str_failed.draw(message_x, message_y); | |
| break; | |
| } | |
| } | |
| static void draw_int(int x, int y, int v){ | |
| auto p10 = [](int d){ | |
| int r = 1; | |
| for(int i = 0; i < d; ++i){ r *= 10; } | |
| return r; | |
| }; | |
| int d = 0; | |
| for(int i = 0; i < d; ++i){ | |
| pattern::num[(v / p10(i)) % 10]->draw(x + i * 5, y); | |
| } | |
| } | |
| static void draw_fn(int x, int y, int a, int b, int c){ | |
| int ar[] = { a, b, c }; | |
| for(int i = 0; i < 3; ++i){ | |
| switch(ar[i]){ | |
| case 0: | |
| pattern::str_sin.draw(x + i * 20, y); | |
| break; | |
| case 1: | |
| pattern::str_cos.draw(x + i * 20, y); | |
| break; | |
| case 2: | |
| pattern::str_tan.draw(x + i * 20, y); | |
| break; | |
| } | |
| } | |
| } | |
| void join_generate_thread() const{ | |
| for(unsigned int i = 0; i < thread_num; ++i){ | |
| if(mandelbrot_instance.thread_array[i].joinable()){ | |
| mandelbrot_instance.thread_array[i].join(); | |
| } | |
| } | |
| } | |
| void join_all_thread() const{ | |
| if(mandelbrot_instance.bmp_thread.joinable()){ | |
| mandelbrot_instance.bmp_thread.join(); | |
| } | |
| join_generate_thread(); | |
| } | |
| static void launch_draw_thread( | |
| std::function<void(int, int, int, rgb_type)> draw_pixel, | |
| int width, | |
| int height, | |
| const thread_data_draw &data | |
| ){ | |
| mandelbrot_instance.mutex_make_rec_thread.lock(); | |
| set_all_generate_flags(true); | |
| for(unsigned int i = 0; i < thread_num - 1; ++i){ | |
| common_data_array[i].set_pixel = draw_pixel; | |
| common_data_array[i].size.first = width; | |
| common_data_array[i].size.second = height; | |
| common_data_array[i].height_begin_end.first = i * height / thread_num; | |
| common_data_array[i].height_begin_end.second = (i + 1) * height / thread_num - 1; | |
| mandelbrot_instance.thread_array[i] = std::thread(&mandelbrot::make, std::ref(mandelbrot_instance), i, std::ref(common_data_array[i]), std::ref(data)); | |
| } | |
| { | |
| unsigned int n = thread_num - 1; | |
| common_data_array[n].set_pixel = draw_pixel; | |
| common_data_array[n].size.first = width; | |
| common_data_array[n].size.second = height; | |
| common_data_array[n].height_begin_end.first = n * height / thread_num; | |
| common_data_array[n].height_begin_end.second = height; | |
| mandelbrot_instance.thread_array[n] = std::thread(&mandelbrot::make, std::ref(mandelbrot_instance), n, std::ref(common_data_array[n]), std::ref(data)); | |
| } | |
| mandelbrot_instance.mutex_make_rec_thread.unlock(); | |
| } | |
| std::function<void(int, int, int, rgb_type)> draw_pixel; | |
| int | |
| gcount, | |
| dad_x_begin, dad_x_end, | |
| dad_y_begin, dad_y_end; | |
| int buffer_handle; | |
| thread_data_draw current_data; | |
| mode_enum mode; | |
| message_enum message; | |
| dad_enum dad; | |
| std::vector<thread_data_draw> cache_array; | |
| }; | |
| int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ | |
| if( | |
| ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || | |
| SetGraphMode(const_value::window_width, const_value::window_height, 32) != DX_CHANGESCREEN_OK || | |
| SetMainWindowText("m_shima2 ver 0.0.0") != 0 || | |
| DxLib_Init() != 0 | |
| ){ return -1; } | |
| pattern_surface.load(); | |
| ui ui_instance; | |
| for(; ; ){ | |
| input_manager(); | |
| if(ProcessMessage() == -1){ | |
| exit_flag = true; | |
| ui_instance.join_all_thread(); | |
| break; | |
| } | |
| ui_instance.proc(); | |
| ui_instance.draw(); | |
| ScreenFlip(); | |
| } | |
| DxLib_End(); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment