diff --git a/charge/charge.c b/charge/charge.c index 3be7c4b750e7c355d56f126dabeb1ff1eb061e12..a0ae22c4435ccf7465934c1430ed1be6306850a2 100644 --- a/charge/charge.c +++ b/charge/charge.c @@ -9,20 +9,94 @@ * */ #include "../draw/draw.h" -#include "../vector/vector.h" +#include "../vec2/vec2.h" #include "../utilities/utils.h" #include "charge.h" bool compute_e(charge_t c, vec2 p, double eps, vec2 *e) { + vec2 qP = vec2_sub(p, c.pos); + double norm = vec2_norm(qP); + double bigE = K * c.q / pow(norm, 2); // E = k * (Q / r^2) + *e = vec2_mul(vec2_div(qP, norm), bigE); // e = E * qP / ||qP|| + return (norm > eps); } bool compute_total_normalized_e(charge_t *charges, int num_charges, vec2 p, double eps, vec2 *e) { + vec2 sum; + vec2 tmp_e; + + for (int i = 0; i < num_charges; i++) + { + if (!compute_e(charges[i], p, eps, &tmp_e)) + return false; + sum = vec2_add(sum, tmp_e); + } + + *e = sum; + return true; +} + +bool compute_p_next(charge_t *charges, int num_charges, double eps, double delta, vec2 *p, bool opposed) +{ + vec2 v; + bool can_draw = compute_total_normalized_e(charges, num_charges, *p, eps, &v); + + v = vec2_div(vec2_mul(v, delta), vec2_norm(v)); + + if (opposed) + *p = vec2_sub(*p, v); // P + deltax * E / ||E|| + else + *p = vec2_add(*p, v); // P - deltax * E / ||E|| + + return can_draw; +} + +bool pos_contrain_in_universe(vec2 pos, double x0, double x1, double y0, double y1) +{ + return (pos.x <= x1 && pos.x >= x0 && pos.y <= y1 && pos.y >= y0); +} + +bool pos_not_too_close(vec2 p, charge_t *c, int num_charges) +{ + for (int i = 0; i < num_charges; i++) + { + double norm = vec2_norm(vec2_sub(p, c[i].pos)); + if (norm < EPS) + return false; + } + return true; +} + +bool field_line_segment(struct gfx_context_t *ctxt, charge_t *charges, int num_charges, double dx, double x0, double x1, double y0, double y1, vec2 old, vec2 p, bool side) +{ + while (pos_contrain_in_universe(p, x0, x1, y0, y1) && pos_not_too_close(p, charges, num_charges)) + { + coordinates_t old_coord = position_to_coordinates(ctxt->width, ctxt->height, x0, x1, y0, y1, old); + coordinates_t pi_coord = position_to_coordinates(ctxt->width, ctxt->height, x0, x1, y0, y1, p); + + gfx_draw_line(ctxt, pi_coord, old_coord, 0xFFFFFF); + + old = p; // Save current point + compute_p_next(charges, num_charges, EPS, dx, &p, side); + } + + return true; } -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) +void 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 p = pos0; + vec2 old = p; + + bool ended = false; + + for (int side = 0; side <= 1; side++) + { + old = pos0; // Reset to start from the same point for both sides + field_line_segment(ctxt, charges, num_charges, dx, x0, x1, y0, y1, old, p, (bool)side); + } } void draw_charges(struct gfx_context_t *ctxt, charge_t *charges, int num_charges, double x0, double x1, double y0, double y1) @@ -34,8 +108,7 @@ void draw_charges(struct gfx_context_t *ctxt, charge_t *charges, int num_charges coordinates_t ch0; coordinates_t ch1; - int radius = 25; - int chargePadding = 10; + int chargePadding = CHARGE_RADIUS / 2; // Draw charges for (int i = 0; i < num_charges; i++) @@ -53,7 +126,7 @@ void draw_charges(struct gfx_context_t *ctxt, charge_t *charges, int num_charges gfx_draw_line(ctxt, coordinates_create(chCoord.row - chargePadding, chCoord.column), coordinates_create(chCoord.row + chargePadding, chCoord.column), COLOR_RED); } - gfx_draw_circle(ctxt, chCoord, radius, charges[i].q < 0 ? COLOR_BLUE : COLOR_RED); + gfx_draw_circle(ctxt, chCoord, CHARGE_RADIUS, charges[i].q < 0 ? COLOR_BLUE : COLOR_RED); } } @@ -67,6 +140,6 @@ void generate_points(vec2 points[], int nb_points) x = rand_one(); y = rand_one(); - points[i] = init_vector(x, y); + points[i] = vec2_create(x, y); } } \ No newline at end of file diff --git a/charge/charge.h b/charge/charge.h index 2e4e651c6aa1640201f9f068ef974eae9da36600..b2c7a2a15dfd31d6dca90f51f1d5e7d2383830e0 100644 --- a/charge/charge.h +++ b/charge/charge.h @@ -11,10 +11,15 @@ #ifndef _CHARGE_H_ #define _CHARGE_H_ +#define K 8.988e9 +#define E 1.602e-19 +#define CHARGE_RADIUS 10 +#define EPS 0.025 + #include <stdlib.h> #include <stdbool.h> #include "../utilities/utils.h" -#include "../vector/vector.h" +#include "../vec2/vec2.h" #include "../gfx/gfx.h" /** @@ -42,23 +47,52 @@ bool compute_total_normalized_e(charge_t *charges, int num_charges, vec2 p, double eps, vec2 *e); /** - * @brief Compute and then draw all the points belonging to a field line, - * starting from pos0 + * @brief Compute the next particle * - * @param ctxt Context to draw on * @param charges All the charges * @param num_charges Number of charges in action - * @param dx Space between computed points on the field line - * @param pos0 First post to start the computing of the field line - * @param x0 Minal x of the universe - * @param x1 Maximal x of the universe - * @param y0 Minal y of the universe - * @param y1 Maximal y of the universe - * @return bool false if pos0 not a valid pos (e.g. too close to a charge) + * @param eps Minimal gap between field and charge + * @param delta Distance between two points in the field line + * @param p Current point + * @param opposed Is the next point towards charge + * @return true + * @return false + */ +bool compute_p_next(charge_t *charges, int num_charges, double eps, double delta, vec2 *p, bool opposed); + +/** + * @brief Draw a segment of a field line between two given points + * + * @param ctxt Context to draw on + * @param charges All the charges + * @param num_charges Number of charges + * @param dx Distance between next point and current point + * @param x0 Minimal X + * @param x1 Maximal X + * @param y0 Minimal Y + * @param y1 Maximal Y + * @param old Old pos + * @param p Next pos + * @param side Side of the line + * @return true + * @return false + */ +bool field_line_segment(struct gfx_context_t *ctxt, charge_t *charges, int num_charges, double dx, double x0, double x1, double y0, double y1, vec2 old, vec2 p, bool side); + +/** + * @brief Draw a field line + * + * @param ctxt Context to draw on + * @param charges All the charges in action + * @param num_charges Number of charges + * @param dx Distance between current and next point to draw line + * @param pos0 Line starting point (will draw on both side of the point) + * @param x0 Minimal X + * @param x1 Maximal X + * @param y0 Minimal Y + * @param y1 Maximal Y */ -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); +void 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); /** * @brief Draw all charges diff --git a/main.c b/main.c index afbf648e46f6fda8adb88094e21225ac6c407c76..1af15b703290bc774cdbc7c23d47092dc59df118 100644 --- a/main.c +++ b/main.c @@ -21,8 +21,9 @@ #define x1 1 // Maximal x of the universe #define y0 0 // Minimal y of the universe #define y1 1 // Maximal y of the universe -#define NB_CHARGES 2 -#define NB_POINTS 100 +#define NB_CHARGES 3 +#define NB_POINTS 200 +#define DELTA (1 / sqrt(pow(WINDOW_WIDTH, 2) + pow(WINDOW_HEIGHT, 2))) int main(void) { @@ -36,17 +37,21 @@ int main(void) return EXIT_FAILURE; } + // Generate all the charges charge_t charges[NB_CHARGES]; - charges[0] = charge_create(10, init_vector(0.25, 0.5)); - charges[1] = charge_create(-10, init_vector(0.75, 0.5)); + for (int i = 0; i < NB_CHARGES; i++) + { + charges[i] = charge_create(rand_one() / E * (rand_one() > 0.5 ? 1 : -1), vec2_create(rand_one(), rand_one())); + } draw_charges(ctxt, charges, NB_CHARGES, x0, x1, y0, y1); + // Generate all the points vec2 points[NB_POINTS]; generate_points(points, NB_POINTS); for (int i = 0; i < NB_POINTS; i++) { coordinates_t c = position_to_coordinates(WINDOW_WIDTH, WINDOW_HEIGHT, x0, x1, y0, y1, points[i]); - gfx_putpixel(ctxt, c.column, c.row, COLOR_WHITE); + draw_field_line(ctxt, charges, NB_CHARGES, DELTA, points[i], x0, x1, y0, y1); } // GFX Draw loop diff --git a/utilities/utils.c b/utilities/utils.c index cd7d604717b1200c3911cab9a6176bc6e011609c..c683fd200a3d027ec0322f5bf7c731d4ae020380 100644 --- a/utilities/utils.c +++ b/utilities/utils.c @@ -1,6 +1,6 @@ #include <math.h> #include <stdlib.h> -#include "../vector/vector.h" +#include "../vec2/vec2.h" #include "utils.h" // Transform a position in the univers [x0,y0]x[x1,y1] to a screen position diff --git a/utilities/utils.h b/utilities/utils.h index 29b6372babf8c57c443852669d78d23f53455a02..8a9948d880dce02e3f440dc645e1131550151310 100644 --- a/utilities/utils.h +++ b/utilities/utils.h @@ -1,11 +1,8 @@ #ifndef _UTILS_H_ #define _UTILS_H_ -#define K 8.988e9; -#define E 1.602e-19; - #include <stdint.h> -#include "../vector/vector.h" +#include "../vec2/vec2.h" #include "../draw/draw.h" typedef struct _charge_t