diff --git a/.gitignore b/.gitignore index ad64b2e38ab08b900213788d1e323475cd83d27e..da8aa77dbb4ff2ebb7cfdebefd10b52de0d79397 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ build *.o *.pdf +main diff --git a/Makefile b/Makefile index dfb9627faa32ad11d7542fccf530da0016874a95..25c7843b30c09ce153d77d22fb524c49cf44b0d0 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,12 @@ CC:=gcc CFLAGS:=-g -O3 -Wall -Wextra -fsanitize=address -fsanitize=leak -std=gnu11 -LDFLAGS:=-lm +LDFLAGS:=-lm VPATH:=utils utils/vec2 utils/gfx src OBJFILES:= vec2.o utils.o field.o draw.o gfx.o TESTS:= draw_tests field_tests +all: main + main: main.o $(OBJFILES) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lSDL2 diff --git a/src/field.c b/src/field.c index ec6f1e284904cc8eac72f3d81ba74502b8607c24..89afa5291cbae8e9855fbece18b9772fb6126f48 100644 --- a/src/field.c +++ b/src/field.c @@ -1,19 +1,12 @@ #include <stdbool.h> -#include <stdlib.h> -#include <time.h> - #include "draw.h" #include "field.h" -#include "draw.h" -#include "../utils/utils.h" + #define SIGN_SIZE 10 #define CHARGE_R 25 -// Compute E*qP/norm(qP) -// Return false if norm(qP) < eps -/// qP = vectoriel(P-q) -/// Compute the vector value of the field generated by a charge at a given point in space. + bool compute_e(charge_t c, vec2 p, double eps, vec2 *e) { vec2 relative_position = vec2_sub(p, c.pos); if (vec2_norm(relative_position) < eps) return false; @@ -22,8 +15,7 @@ bool compute_e(charge_t c, vec2 p, double eps, vec2 *e) { return true; } -// Compute the normalized sum of Ei*qiP/norm(qiP) -// Return false if for some qiP, norm(qiP) < eps + bool compute_total_normalized_e(charge_t *charges, int num_charges, vec2 p, double eps, vec2 *e) { *e = vec2_create_zero(); vec2 ei = vec2_create_zero(); @@ -35,38 +27,33 @@ bool compute_total_normalized_e(charge_t *charges, int num_charges, vec2 p, doub return true; } -double compute_delta_x(){ +double compute_delta_x() { double result = pow(WID, 2) + pow(HEI, 2); result = sqrt(result); return 1 / result; } -bool is_in_screen(coordinates_t pos){ - if(pos.column > WID) - return false; - - if(pos.row > HEI) - return false; - - return true; +bool is_in_screen(coordinates_t pos) { + // TODO: should this not be "<" instead of "<=" ? + return pos.column <= WID && pos.row <= HEI; } -bool draw_field_line_point(struct gfx_context_t *ctxt, charge_t *charges, int num_charges, double x0, double x1, double y0, double y1, vec2 pos, vec2 *pos_next, double delta){ +bool draw_field_line_point(struct gfx_context_t *ctxt, charge_t *charges, int num_charges, double x0, double x1, double y0, double y1, vec2 pos, vec2 *pos_next, double delta) { vec2 e; compute_total_normalized_e(charges, num_charges, pos, 0.01, &e); double norm_e = vec2_norm(e); - // Problème ici + // TODO: "Problème ici" ? pos_next->x = pos.x + delta * (e.x / norm_e); pos_next->y = pos.y + delta * (e.y / norm_e); - if(pos_next->x <= 0 || pos_next->x >= 1 || pos_next->y <= 0 || pos_next->y >= 1) + if (pos_next->x <= 0 || pos_next->x >= 1 || pos_next->y <= 0 || pos_next->y >= 1) return false; coordinates_t coordinate_pos = position_to_coordinates(WID, HEI, x0, x1, y0, y1, pos); coordinates_t coordinate_pos_next = position_to_coordinates(WID, HEI, x0, x1, y0, y1, *pos_next); - if(coordinate_pos_next.column <= 0 || coordinate_pos_next.row <= 0) + if (coordinate_pos_next.column <= 0 || coordinate_pos_next.row <= 0) return false; gfx_draw_line(ctxt, coordinate_pos, coordinate_pos_next, COLOR_YELLOW); @@ -74,9 +61,9 @@ bool draw_field_line_point(struct gfx_context_t *ctxt, charge_t *charges, int nu return !is_in_screen(coordinate_pos); } -bool line_reach_charge(vec2 pos, charge_t * charges, double num_charges, double dx){ - for (int j = 0; j < num_charges; j++){ - if(vec2_norm(vec2_sub(pos, charges[j].pos)) < dx / HEI){ +bool line_reach_charge(vec2 pos, charge_t *charges, int num_charges, double dx) { + for (int j = 0; j < num_charges; ++j) { + if (vec2_norm(vec2_sub(pos, charges[j].pos)) < dx / HEI) { return true; } } @@ -84,10 +71,10 @@ bool line_reach_charge(vec2 pos, charge_t * charges, double num_charges, double } -// Compute and then draw all the points belonging to a field line, -// starting from pos0. -// Returns false if pos0 is not a valid position -// (for example if pos0 is too close to a charge). +/// Compute and then draw all the points belonging to a field line, +/// starting from pos0. +/// Returns false if pos0 is not a valid position +/// (for example if pos0 is too close to a charge). static bool draw_field_line(struct gfx_context_t *ctxt, charge_t *charges, int num_charges, double dx, vec2 pos0, double x0, double x1, double y0, double y1) { vec2 pos_positive = vec2_create(pos0.x, pos0.y); vec2 pos_negative = vec2_create(pos0.x, pos0.y); @@ -97,18 +84,17 @@ static bool draw_field_line(struct gfx_context_t *ctxt, charge_t *charges, int n bool stop_negative = false; // * 5 à supprimer lorsque le code est optimisé double delta = compute_delta_x(); - int max_for = 100000; - for (int i = 0; i < max_for && (!stop_positive || !stop_negative); i++) - { + int max_for = 100000; + for (int i = 0; i < max_for && (!stop_positive || !stop_negative); i++) { stop_positive = line_reach_charge(pos_positive, charges, num_charges, dx); stop_negative = line_reach_charge(pos_negative, charges, num_charges, dx); - if(!stop_positive){ + if (!stop_positive) { stop_positive = draw_field_line_point(ctxt, charges, num_charges, x0, x1, y0, y1, pos_positive, &pos_next_positive, delta); pos_positive = pos_next_positive; } - if(!stop_negative){ + if (!stop_negative) { stop_negative = draw_field_line_point(ctxt, charges, num_charges, x0, x1, y0, y1, pos_negative, &pos_next_negative, -delta); pos_negative = pos_next_negative; } @@ -117,12 +103,11 @@ static bool draw_field_line(struct gfx_context_t *ctxt, charge_t *charges, int n return !stop_positive || !stop_negative; } -// Draw all the charges -// A circle with minus sign for negative charges -// A circle with a plus sign for positive charges +/// Draw all the charges +/// A circle with minus sign for negative charges +/// A circle with a plus sign for positive charges static void draw_charges(struct gfx_context_t *context, charge_t *charges, int num_charges, double x0, double x1, double y0, double y1) { - for (int i = 0; i < num_charges; i++) - { + for (int i = 0; i < num_charges; i++) { coordinates_t charge_center = position_to_coordinates(WID, HEI, x0, x1, y0, y1, charges[i].pos); gfx_draw_circle(context, charge_center, CHARGE_R, COLOR_WHITE); @@ -152,7 +137,6 @@ void draw_everything( double dx, double x0, double x1, double y0, double y1) { - srand(time(NULL)); draw_charges(ctxt, charges, num_charges, x0, x1, y0, y1); for (int i = 0; i < num_lines; ++i) { vec2 pos0 = vec2_create(rand_one(), rand_one()); diff --git a/src/field.h b/src/field.h index 01b6729fb5caf56a3dee485b875e6e4acbeaf82b..4f7c4bda28992220896da98df8282efd8c775677 100644 --- a/src/field.h +++ b/src/field.h @@ -1,27 +1,34 @@ #ifndef _PHYSIQUE_H_ #define _PHYSIQUE_H_ -#include "../utils/vec2/vec2.h" -#include "../utils/gfx/gfx.h" -#include "../utils/utils.h" #include <stdio.h> +#include "../utils/utils.h" +#include "../utils/gfx/gfx.h" +#include "../utils/vec2/vec2.h" #define SIDE_LEN 1000 #define WID SIDE_LEN #define HEI WID -// Compute E*qP/norm(qP) -// Return false if norm(qP) < eps + +/// Compute E*qP/norm(qP) +/// Return false if norm(qP) < eps +/// Compute the vector value of the field generated by a charge at a given point in space. +/// qP = vectoriel(P-q) bool compute_e(charge_t c, vec2 p, double eps, vec2 *e); -// Compute the normalized sum of Ei*qiP/norm(qiP) -// Return false if for some qiP, norm(qiP) < eps + +/// Compute the normalized sum of Ei*qiP/norm(qiP) +/// Return false if for some qiP, norm(qiP) < eps bool compute_total_normalized_e(charge_t *charges, int num_charges, vec2 p, double eps, vec2 *e); -bool line_reach_charge(vec2 pos, charge_t * charges, double num_charges, double dx); + +bool line_reach_charge(vec2 pos, charge_t *charges, int num_charges, double dx); + bool is_in_screen(coordinates_t pos); + void draw_everything( struct gfx_context_t *ctxt, charge_t *charges, @@ -31,4 +38,5 @@ void draw_everything( double x0, double x1, double y0, double y1); + #endif diff --git a/utils/utils.c b/utils/utils.c index ab79bc32f2b3e7651de8ab569dcc71caa3578cbf..24feb7a083f988fc06b1ebe061aa475c053d15a1 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -1,29 +1,39 @@ -#include "vec2/vec2.h" -#include "utils.h" #include <math.h> #include <stdlib.h> +#include <time.h> +#include "utils.h" +#include "vec2/vec2.h" + + +coordinates_t coordinates_create(int row_, int column_) { + coordinates_t c = {.row = row_, .column = column_}; + return c; +} + -coordinates_t coordinates_create(int row_, int column_) -{ - coordinates_t c = {.row = row_, .column = column_}; - return c; +coordinates_t position_to_coordinates(int width, int height, double x0, double x1, double y0, double y1, vec2 pos) { + double dx = x1 - x0; + double dy = y1 - y0; + return coordinates_create((int) round(height * (pos.y - y0) / dy), (int) round(width * (pos.x - x0) / dx)); } -// Transform a position in the univers [x0,y0]x[x1,y1] to a screen position -coordinates_t position_to_coordinates(int width, int height, double x0, double x1, double y0, double y1, vec2 pos) -{ - double dx = x1 - x0; - double dy = y1 - y0; - return coordinates_create((int)round(height * (pos.y - y0) / dy), (int)round(width * (pos.x - x0) / dx)); + +int rand_num() { + static bool rand_initialised = false; + if (!rand_initialised) { + srand(time(NULL)); + rand_initialised = true; + } + return rand(); } -double rand_one() -{ - return (double)rand() / (double)RAND_MAX; + +double rand_one() { + return (double) rand_num() / (double) RAND_MAX; } -charge_t charge_create(double q, vec2 pos) -{ - charge_t c = {.q = q, .pos = pos}; - return c; -} \ No newline at end of file + +charge_t charge_create(double q, vec2 pos) { + charge_t c = {.q = q, .pos = pos}; + return c; +} diff --git a/utils/utils.h b/utils/utils.h index 43c02948c138c7460a471032be4ddfd05626729a..829dff1eefba7a28944031e13767f65caa9ff121 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -2,29 +2,39 @@ #define _UTILS_H_ #include <stdint.h> +#include "vec2/vec2.h" + static const double K = 8.988e9; static const double E = 1.602e-19; -typedef struct -{ - uint32_t row; - uint32_t column; + +typedef struct { + uint32_t row; + uint32_t column; } coordinates_t; -typedef struct -{ - double q; - vec2 pos; + +typedef struct { + double q; + vec2 pos; } charge_t; + coordinates_t coordinates_create(int row_, int column_); -// Transform a position in the univers [x0,y0]x[x1,y1] to a screen position + +/// transform a position in the universe [x0,y0]x[x1,y1] to a screen position coordinates_t position_to_coordinates(int width, int height, double x0, double x1, double y0, double y1, vec2 pos); + +int rand_num(); + + double rand_one(); + charge_t charge_create(double q, vec2 pos); -#endif \ No newline at end of file + +#endif