Fractol 1.0
A fractal visualization project implemented in C.
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1/* ************************************************************************** */
2/* */
3/* ::: :::::::: */
4/* main.c :+: :+: :+: */
5/* +:+ +:+ +:+ */
6/* By: meghribe <meghribe@student.42barcelon +#+ +:+ +#+ */
7/* +#+#+#+#+#+ +#+ */
8/* Created: 2025/01/04 12:47:18 by meghribe #+# #+# */
9/* Updated: 2025/01/05 12:54:03 by meghribe ### ########.fr */
10/* */
11/* ************************************************************************** */
12
13#include "fractol.h"
14
15/**
16 * @file main.c
17 * @brief Entry point for the Fractol application.
18 *
19 * This file contains the main function and orchestrates the entire fractal
20 * rendering process. It handles:
21 * - Command-line argument validation to ensure correct input.
22 * - Initialization of the fractal type and parameters (Julia or Mandelbrot)
23 * - Setuup of the rendering environment using the MLX42 graphics liibrary,
24 * including the creation of the window and image bufffer.
25 * - Fractal rendering based on the user-specified parameters.
26 * - Configuration of interactivee event hooks for keyboard and scroll inputs.
27 * - Continuous updates through the main event loop.
28 *
29 * The program terminates gracefully on completion or reports error for invalid
30 * inputs.
31 */
32
33/**
34 * @brief Validates if a string represents a valid number.
35 *
36 * This function checks iff the input string is a valid number, considering:
37 * - Optional leading spaces or tabs.
38 * - An optional sign (+/-).
39 * - At least one digit.
40 * - At most one decimal point with digits before or after it.
41 * Invalid cases include multiple decimal points, invalid characters,
42 * or empty strings.
43 *
44 * @param str Input string to validate
45 * @return 1 if the string is a valid number, 0 otherwise.
46 */
47static int is_valid_number(const char *str)
48{
49 int i;
50 int valid_status[2];
51
52 i = 0;
53 valid_status[HAS_DIGIT] = 0;
54 valid_status[HAS_POINT] = 0;
55 while (str[i] == 32 || (str[i] >= 9 && str[i] <= 13))
56 i++;
57 if (str[i] == '-' || str[i] == '+')
58 i++;
59 while (str[i] >= '0' && str[i] <= '9')
60 {
61 valid_status[HAS_DIGIT] = 1;
62 i++;
63 }
64 if (str[i] == '.')
65 {
66 valid_status[HAS_POINT] = 1;
67 i++;
68 }
69 if (valid_status[HAS_POINT] && (str[i] < '0' || str[i] > '9'))
70 return (0);
71 while (str[i] >= '0' && str[i] <= '9')
72 i++;
73 return (valid_status[HAS_DIGIT] && str[i] == '\0');
74}
75
76/**
77 * @brief Prints an error message and terminates the program.
78 *
79 * This function displays an error, the correct usage off the program, and
80 * list of available fractal types with examples. It then terminates the
81 * program with a failure status.
82 *
83 * @param message Error message to display.
84 * @param argv Command-line arguments, used to show the program name in
85 * usage examples.
86 */
87static void exit_with_error(const char *message, char *argv[])
88{
89 fr_putstr_fd(LIGHT_RED "Error: ", 2);
90 fr_putstr_fd((char *)message, 2);
91 fr_putstr_fd("\n" RESET, 2);
93 fr_putstr_fd(argv[0], 2);
94 fr_putstr_fd(" <fractal_type> [parameters]\n" RESET, 2);
95 fr_putstr_fd(LIGHT_RED "Available fractal types:\n" RESET, 2);
96 fr_putstr_fd(LIGHT_GOLD "\tmandelbrot" RESET, 2);
97 fr_putstr_fd("\t\tDisplays the Mandelbrot set.\n", 2);
98 fr_putstr_fd(LIGHT_GOLD "\tjulia [c_re c_im]" RESET, 2);
99 fr_putstr_fd("\tDisplays the Julia set.\n", 2);
100 fr_putstr_fd(LIGHT_RED "Example: " LIGHT_GREEN, 2);
101 fr_putstr_fd(argv[0], 2);
102 fr_putstr_fd(" julia 0.285 -0.01\n" RESET, 2);
103 exit(EXIT_FAILURE);
104}
105
106/**
107 * @brief Validates the command-line arguments for fractal rendering.
108 *
109 * This function checks that the user has specified a valid fractal type
110 * and the correct parameters. The supported fractals and their requirements
111 * are:
112 * - `mandelbrot`: No additional arguments.
113 * - `julia`: Requires exactly two valid numbers representing the real and
114 * imaginary part of the parameter.
115 *
116 * If the arguments are invalid, the function calls `exit_with_error()` to
117 * display an appropiate error message and terminate the program.
118 *
119 * @param argc Number of command-line arguments passed to the program.
120 * @param argv Array of command-line argument strings.
121 */
122static void validate_arguments(int argc, char *argv[])
123{
124 char *e_msg[5];
125
126 e_msg[NO_TYPE] = "No fractal type specified.";
127 e_msg[INVALID_TYPE] = "Invalid fractal type. Use 'julia' or 'mandelbrot'.";
128 e_msg[JULIA_ARGS] = "Julia needs: 'julia <c_re> <c_im>'.";
129 e_msg[JULIA_NUM] = "Julia parameters must be valid numbers.";
130 e_msg[MANDELBROT_ARGS] = "Mandelbrot needs: 'mandelbrot'.";
131 if (argc < 2)
132 exit_with_error(e_msg[NO_TYPE], argv);
133 if (ft_strcmp(argv[1], "mandelbrot") == 0)
134 {
135 if (argc != 2)
136 exit_with_error(e_msg[MANDELBROT_ARGS], argv);
137 return ;
138 }
139 if (ft_strcmp(argv[1], "julia") == 0)
140 {
141 if (argc != 4)
142 exit_with_error(e_msg[JULIA_ARGS], argv);
143 if (!is_valid_number(argv[2]) || !is_valid_number(argv[3]))
144 exit_with_error(e_msg[JULIA_NUM], argv);
145 }
146 else
147 exit_with_error(e_msg[INVALID_TYPE], argv);
148}
149
150/**
151 * @brief Initializes the MLX42 rendering environment.
152 *
153 * This function sets up the environment for rendering fractals by:
154 * - Creating an MLX42 window with thee given title.
155 * - Allocating an image buffer for rendering.
156 * - Setting initial offsets and zoom level for the fractal.
157 *
158 * If Julia set parameters (`c[COMPLEX_RE]` or `c[COMPLEX_IM]`) are outside
159 * the range [-2.0, 2.0], it issues a warning about potential visual effects.
160 * The function terminates the program in case of initialization failures.
161 *
162 * @param data Pointer to the data structure containing fractal information,
163 * offsets, zoom, and MLX42 resources.
164 * @param argv Array of argument strings, where argv[1] is used as the window
165 * title.
166 */
167static void initialize_window(t_data *data, char *argv[])
168{
169 if ((data->c[COMPLEX_RE] > 2.0 || data->c[COMPLEX_RE] < -2
170 || data->c[COMPLEX_IM] > 2.0 || data->c[COMPLEX_IM] < -2))
171 {
172 fr_putstr_fd(LIGHT_GOLD "Warning: The values for Julia are", 1);
173 fr_putstr_fd(" outside the common range [-2.0, 2.0]\n", 1);
174 fr_putstr_fd(RESET "This may produce unusual or", 1);
175 fr_putstr_fd(" less interesting fractals.\n", 1);
176 }
177 data->mlx = mlx_init(WIDTH, HEIGHT, argv[1], false);
178 if (!data->mlx)
179 exit (EXIT_FAILURE);
180 data->img = mlx_new_image(data->mlx, WIDTH, HEIGHT);
181 if (!data->img)
182 {
183 mlx_terminate(data->mlx);
184 exit (EXIT_FAILURE);
185 }
186 if (mlx_image_to_window(data->mlx, data->img, 0, 0) == -1)
187 {
188 mlx_terminate(data->mlx);
189 exit (EXIT_FAILURE);
190 }
191 data->offset[OFFSET_X] = 0.0;
192 data->offset[OFFSET_Y] = 0.0;
193 data->zoom = 1.0;
194}
195
196/**
197 * @brief Main entry point for the fractal rendering program.
198 *
199 * This function orchestrates the entire fractal rendering process by:
200 * - Validating the command-line arguments to ensure correct fractal type
201 * and parameters.
202 * - Initializing the fractal type, including Julia parameters if applicable.
203 * - Setting up the MLX42 rendering environment, including the window
204 * and image buffer.
205 * - Rendering the chosen fractal based on the input parameters.
206 * - Configuring event hooks for used interaction (keyboard and scroll events).
207 * - Starting the main event loop for continuous interaction and updates.
208 *
209 * @param argc Number of arguments passed to the program.
210 * @param argv Array of argument strings, including the program name and input
211 * parameters.
212 * @return Returns `EXIT_SUCCESS` on successful execution,
213 * or terminates on error.
214 */
215int main(int argc, char *argv[])
216{
217 t_data data;
218 char *error;
219
220 validate_arguments(argc, argv);
221 if (ft_strcmp(argv[1], "julia") == 0)
222 {
223 error = "Julia parameters must be valid numbers.";
224 data.fractal_type = JULIA;
225 data.c[COMPLEX_RE] = ft_atod(argv[2]);
226 data.c[COMPLEX_IM] = ft_atod(argv[3]);
227 if (data.c[COMPLEX_RE] > INT_MAX || data.c[COMPLEX_RE] < INT_MIN)
228 return (exit_with_error(error, argv), 1);
229 if (data.c[COMPLEX_IM] > INT_MAX || data.c[COMPLEX_IM] < INT_MIN)
230 return (exit_with_error(error, argv), 1);
231 }
232 else if (ft_strcmp(argv[1], "mandelbrot") == 0)
234 initialize_window(&data, argv);
235 render_fractal(&data);
236 mlx_key_hook(data.mlx, handle_key, &data);
237 mlx_scroll_hook(data.mlx, handle_scroll, &data);
238 mlx_loop(data.mlx);
239 mlx_terminate(data.mlx);
240 return (EXIT_SUCCESS);
241}
void render_fractal(t_data *data)
Renders the chosen fractal on the screen.
Definition calcs.c:108
@ MANDELBROT
Definition fractol.h:25
@ JULIA
Definition fractol.h:26
@ HAS_POINT
Definition fractol.h:62
@ HAS_DIGIT
Definition fractol.h:61
int ft_strcmp(const char *s1, const char *s2)
Compares two strings.
Definition utils.c:51
#define WIDTH
Definition fractol.h:188
int fr_putstr_fd(char *s, int fd)
Writes a string to a file descriptor.
Definition utils.c:109
@ JULIA_NUM
Definition fractol.h:73
@ INVALID_TYPE
Definition fractol.h:71
@ NO_TYPE
Definition fractol.h:70
@ JULIA_ARGS
Definition fractol.h:72
@ MANDELBROT_ARGS
Definition fractol.h:74
#define LIGHT_GREEN
Definition fractol.h:197
#define LIGHT_RED
Definition fractol.h:195
@ OFFSET_Y
Definition fractol.h:35
@ OFFSET_X
Definition fractol.h:34
@ COMPLEX_IM
Definition fractol.h:53
@ COMPLEX_RE
Definition fractol.h:52
void handle_key(mlx_key_data_t keydata, void *param)
Handles key inputs.
Definition utils.c:64
#define RESET
Definition fractol.h:194
double ft_atod(const char *str)
Converts a string to a double.
Definition utils.c:19
void handle_scroll(double xdelta, double ydelta, void *param)
Handles scroll inputs.
Definition utils.c:91
#define HEIGHT
Definition fractol.h:189
#define LIGHT_GOLD
Definition fractol.h:196
int main(int argc, char *argv[])
Main entry point for the fractal rendering program.
Definition main.c:215
static void exit_with_error(const char *message, char *argv[])
Prints an error message and terminates the program.
Definition main.c:87
static int is_valid_number(const char *str)
Validates if a string represents a valid number.
Definition main.c:47
static void validate_arguments(int argc, char *argv[])
Validates the command-line arguments for fractal rendering.
Definition main.c:122
static void initialize_window(t_data *data, char *argv[])
Initializes the MLX42 rendering environment.
Definition main.c:167
Data structure for fractal rendering.
Definition fractol.h:92
double offset[2]
Definition fractol.h:95
t_fractal_type fractal_type
Definition fractol.h:98
mlx_image_t * img
Definition fractol.h:97
mlx_t * mlx
Definition fractol.h:96
double c[2]
Definition fractol.h:94
double zoom
Definition fractol.h:93