diff --git a/MandelbrotDiscovery/MandelbrotDiscovery.vcxproj b/MandelbrotDiscovery/MandelbrotDiscovery.vcxproj index 9b1e7ae..ef4b091 100644 --- a/MandelbrotDiscovery/MandelbrotDiscovery.vcxproj +++ b/MandelbrotDiscovery/MandelbrotDiscovery.vcxproj @@ -106,6 +106,7 @@ + diff --git a/MandelbrotDiscovery/MandelbrotDiscovery.vcxproj.filters b/MandelbrotDiscovery/MandelbrotDiscovery.vcxproj.filters index 00b4073..8adbb66 100644 --- a/MandelbrotDiscovery/MandelbrotDiscovery.vcxproj.filters +++ b/MandelbrotDiscovery/MandelbrotDiscovery.vcxproj.filters @@ -22,6 +22,9 @@ MandelbrotDiscovery + + MandelbrotDiscovery + diff --git a/MandelbrotDiscovery/mandelbrot_discovery.h b/MandelbrotDiscovery/mandelbrot_discovery.h index f7fc3c2..6a6d6ce 100644 --- a/MandelbrotDiscovery/mandelbrot_discovery.h +++ b/MandelbrotDiscovery/mandelbrot_discovery.h @@ -38,6 +38,8 @@ #include extern auto mandelbrot_discovery_rescale() -> void; + extern auto mandelbrot_discovery_cmd_res(const std::string& str_cmd, int& frac, std::string& str_cmd_result) -> bool; + extern auto mandelbrot_discovery_cmd_itr(const std::string& str_cmd, unsigned& iter, std::string& str_cmd_result) -> bool; namespace mandelbrot_discovery_detail { @@ -405,7 +407,7 @@ local_rectangle_ref.center().get_x() + local_rectangle_ref.dx_half(), local_rectangle_ref.center().get_y() - local_rectangle_ref.dy_half(), local_rectangle_ref.center().get_y() + local_rectangle_ref.dy_half(), - my_mandelbrot_iterations + std::uint_fast32_t { my_mandelbrot_iterations } ); mandelbrot_generator_type gen { mandelbrot_config_object }; @@ -601,12 +603,14 @@ write_string("cmd: "); - std::string str_cmd { }; + std::string str_cmd { }; + std::string str_cmd_result { }; + bool do_iterate_and_redraw { }; + int frac2 { }; + unsigned iter { }; read_string(str_cmd); - bool do_iterate_and_redraw { }; - if(str_cmd == "set") { write_string("click to set a point\n"); @@ -618,78 +622,17 @@ std::this_thread::sleep_for(std::chrono::microseconds(static_cast(UINT8_C(20)))); } } - else if( (str_cmd.find("itr", static_cast(UINT8_C(0))) == static_cast(UINT8_C(0))) - && (str_cmd.length() > static_cast(UINT8_C(3)))) + else if(::mandelbrot_discovery_cmd_itr(str_cmd, iter, str_cmd_result)) { - std::uint_fast32_t iter { }; - - const auto result_of_iter_from_chars = - std::from_chars - ( - str_cmd.c_str() + static_cast(UINT8_C(3)), - str_cmd.c_str() + str_cmd.length(), - iter - ); - - const auto err_code = result_of_iter_from_chars.ec; - - if(err_code == std::errc()) - { - my_mandelbrot_iterations = iter; + my_mandelbrot_iterations = iter; - write_string("new max. iterations: " + std::to_string(iter) + "\n"); - } + write_string(str_cmd_result); } - else if( (str_cmd.find("res", static_cast(UINT8_C(0))) == static_cast(UINT8_C(0))) - && (str_cmd.length() > static_cast(UINT8_C(3)))) + else if(::mandelbrot_discovery_cmd_res(str_cmd, frac2, str_cmd_result)) { - // TODO ckormanyos Parse strings of the form: - // res, res1, res1/2, res1/4, res1/8, res1/16, ... - // ... and use this resolution information accordingly. - - // See also code at GodBolt at: https://godbolt.org/z/Wq5nran4o - - if((str_cmd == "res") || (str_cmd == "res1")) - { - my_mandelbrot_frac2_denominator = 1; - - write_string("new resolution having fraction: 1/1\n"); - } - else - { - // Regex pattern to match the required strings. - std::string pattern_str = "res(1)?(/(2|4|8|16))?"; - std::regex pattern(pattern_str); - - std::smatch match; - - if (std::regex_match(str_cmd, match, pattern)) - { - if((match[1].matched) && (match[3].matched)) - { - const std::string str_frac { match[3].str() }; + my_mandelbrot_frac2_denominator = frac2; - int frac2 { }; - - const auto result_of_iter_from_chars = - std::from_chars - ( - str_frac.data(), - str_frac.data() + str_frac.length(), - frac2 - ); - - const auto err_code = result_of_iter_from_chars.ec; - - if(err_code == std::errc()) - { - my_mandelbrot_frac2_denominator = frac2; - - write_string("new resolution having fraction: 1/" + std::to_string(frac2) + "\n"); - } - } - } - } + write_string(str_cmd_result); } else if(str_cmd == "calc") { @@ -1178,7 +1121,7 @@ const int IconId, const int ScreenCoordinateX, const int ScreenCoordinateY> - std::uint_fast32_t mandelbrot_discovery::my_mandelbrot_iterations { static_cast(UINT32_C(400)) }; + unsigned mandelbrot_discovery::my_mandelbrot_iterations { static_cast(UINT16_C(400)) }; template +#include +#include + +auto mandelbrot_discovery_cmd_itr(const std::string& str_cmd, unsigned& iter, std::string& str_cmd_result) -> bool +{ + const bool + cmd_is_itr + { + (str_cmd.find("itr", static_cast(UINT8_C(0))) == static_cast(UINT8_C(0))) + && (str_cmd.length() > static_cast(UINT8_C(3))) + }; + + bool result_cmd_itr_is_ok { false }; + + if(cmd_is_itr) + { + unsigned local_iter { }; + + const auto result_of_iter_from_chars = + std::from_chars + ( + str_cmd.c_str() + static_cast(UINT8_C(3)), + str_cmd.c_str() + str_cmd.length(), + local_iter + ); + + const auto err_code = result_of_iter_from_chars.ec; + + if(err_code == std::errc()) + { + iter = local_iter; + + str_cmd_result = "new max. iterations: " + std::to_string(local_iter) + "\n"; + + result_cmd_itr_is_ok = true; + } + } + + return result_cmd_itr_is_ok; +} + +auto mandelbrot_discovery_cmd_res(const std::string& str_cmd, int& frac2, std::string& str_cmd_result) -> bool +{ + const bool + cmd_is_res + { + (str_cmd.find("res", static_cast(UINT8_C(0))) == static_cast(UINT8_C(0))) + && (str_cmd.length() > static_cast(UINT8_C(3))) + }; + + bool result_cmd_res_is_ok { false }; + + if(cmd_is_res) + { + // Parse strings of the form: res, res1, res1/2, res1/4, res1/8, res1/16. + // See also code at GodBolt at: https://godbolt.org/z/Wq5nran4o + + if((str_cmd == "res") || (str_cmd == "res1")) + { + frac2 = 1; + + str_cmd_result = "new resolution having fraction: 1/1\n"; + + result_cmd_res_is_ok = true; + } + else + { + // Regex pattern to match the required strings. + std::string pattern_str = "res(1)?(/(2|4|8|16))?"; + std::regex pattern(pattern_str); + + std::smatch match; + + if (std::regex_match(str_cmd, match, pattern)) + { + if((match[1].matched) && (match[3].matched)) + { + const std::string str_frac { match[3].str() }; + + int local_frac2 { }; + + const auto result_of_iter_from_chars = + std::from_chars + ( + str_frac.data(), + str_frac.data() + str_frac.length(), + local_frac2 + ); + + const auto err_code = result_of_iter_from_chars.ec; + + if(err_code == std::errc()) + { + frac2 = local_frac2; + + result_cmd_res_is_ok = true; + } + } + } + } + } + + return result_cmd_res_is_ok; +} diff --git a/MandelbrotDiscovery/mandelbrot_discovery_rescale.cpp b/MandelbrotDiscovery/mandelbrot_discovery_rescale.cpp index 0127845..a096945 100644 --- a/MandelbrotDiscovery/mandelbrot_discovery_rescale.cpp +++ b/MandelbrotDiscovery/mandelbrot_discovery_rescale.cpp @@ -1,3 +1,10 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2024. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + #include #include diff --git a/MandelbrotDiscovery/readme.md b/MandelbrotDiscovery/readme.md index 856692d..91f4021 100644 --- a/MandelbrotDiscovery/readme.md +++ b/MandelbrotDiscovery/readme.md @@ -29,29 +29,15 @@ coordinate points of the Mandelbrot set. Build `MandelbrotDiscovery.exe` from the Microsoft(R) VisualStudio(R) solution, `MandelbrotDiscovery.sln` located [here](https://github.com/ckormanyos/mandelbrot/tree/main/MandelbrotDiscovery). -The program uses the classic Win32-API style. Aside from -the JPEG and PNG libraries and image-rescaling, the program -is written in a convenient, lightweight header-only fashion. +Aside from the JPEG/PNG libraries and image-rescaling, +the program is written in a convenient, lightweight +classic Win32-API style. The program is mouse-and-command-driven. Begin a search by starting `MandelbrotDiscovery.exe`. Zooming is accomplished with commands entered in the command window in combination with mouse-clicks in the client area of the Mandelbrot image window. -### Command Summary - -The following commands are supported at the moment (with more planned for the future). - - - help (or ?) - Print the command list. - - set - Enter the set command prior to pointing and clicking to select now coordinates with the mouse. - - calc - The calc command calculated the Mandelbrot image at the currently set coordinate point. It subsequently displays the image after the calculation. - - itrNNNN - Using itrNNNN sets the maximum number of iterations to the appended number. The command itr2000, for instance, sets the maximum number of iterations to $2,000$. Switch $2,000$ for another number like $40,000$ to obtain a maximum iteration count of $40,000$ and so on. The default iteration count at program start is modestly set to $400$. So don't be surprised if higher iteration counts are required for deeper and deeper dives. - - res1/F - Using res1/F sets the fractional resolution based on the default of $768{\times}768$ pixels. The command res1/2, for example, sets the resolution to $384{\times}384$ pixels. The fractions $1/1$, $1/2$, $1/4$, $1/8$ and $1/16$ are supported. The command res (or res1) restores the default resolution. Reduced resolution can significantly decrease computation time when searching via deep diving. - - redo - The command redo simply performs, yet again, the iteration at the coordinate point that is already set. This might be done if, for example, the image was not resolved and the iteration count needs to be increased. You can also exercise the set command one or more times prior to exercising the redo command. - - out - With out you can backstep one single order of magnification at the point that has been set and clicked. This can be done repeatedly if a different zoom pathway is desired even after zooming in to a point. So if you've taken a bit of a wrong turn, just zoom out one or more times and refine your coordinate search. - - exit - Quits the program and closes the image window. - - ### The Startup Windows Upon startup, you should see the default Mandelbrot image. It is a square, gray-tone JPEG @@ -138,13 +124,18 @@ The result of this dive ended up being: ![](https://github.com/ckormanyos/mandelbrot/blob/main/images/discovery/mandelbrot_discovery_dive_example.jpg) -## Additional Program Dynamic Behavior - -The following features (and probably a few more) are TODO both in docs as well as in the program. +### Command Summary -### Changing the Resolution +The following commands are supported at the moment (with more planned for the future). -This feature is TODO both in docs as well as in the program. + - help (or ?) - Print the command list. + - set - Enter the set command prior to pointing and clicking to select now coordinates with the mouse. + - calc - The calc command calculated the Mandelbrot image at the currently set coordinate point. It subsequently displays the image after the calculation. + - itrNNNN - Using itrNNNN sets the maximum number of iterations to the appended number. The command itr2000, for instance, sets the maximum number of iterations to $2,000$. Switch $2,000$ for another number like $40,000$ to obtain a maximum iteration count of $40,000$ and so on. The default iteration count at program start is modestly set to $400$. So don't be surprised if higher iteration counts are required for deeper and deeper dives. + - res1/F - Using res1/F sets the fractional resolution based on the default of $768{\times}768$ pixels. The command res1/2, for example, sets the resolution to $384{\times}384$ pixels. The fractions $1/1$, $1/2$, $1/4$, $1/8$ and $1/16$ are supported. The command res (or res1) restores the default resolution. Reduced resolution can significantly decrease computation time when searching via deep diving. + - redo - The command redo simply performs, yet again, the iteration at the coordinate point that is already set. This might be done if, for example, the image was not resolved and the iteration count needs to be increased. You can also exercise the set command one or more times prior to exercising the redo command. + - out - With out you can backstep one single order of magnification at the point that has been set and clicked. This can be done repeatedly if a different zoom pathway is desired even after zooming in to a point. So if you've taken a bit of a wrong turn, just zoom out one or more times and refine your coordinate search. + - exit - Quits the program and closes the image window. ### Saving and Restoring Previous Work