Skip to content
Snippets Groups Projects
Select Git revision
  • 084c5f96f51472bdb7584a153687931cf8dca92d
  • main default protected
2 results

handler.h

Blame
  • charge.c 3.41 KiB
    #include "charge.h"
    
    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #include "gfx/gfx.h"
    #include "utils.h"
    #include "vector2.h"
    
    const double K = 8.988e9;
    const double ELEMENTARY_CHARGE = 1.602e-19;
    const double THRESHOLD_CHARGES_DISTANCES = 0.5;
    const double EPSILON = 0.05;
    
    double compute_delta_x(int width, int height) {
        return 1.0 / sqrt((width * width) + (height * height));
    }
    
    bool compute_next_point(charge_t *charges, int num_charges, vector2_t current_pos, double eps, vector2_t *new_pos, double dx) {
        vector2_t electric_field;
        if (compute_total_normalized_e(charges, num_charges, current_pos, eps, &electric_field)) {
            *new_pos = vector2_add(current_pos, vector2_multiply(electric_field, dx));
            return true;
        }
    
        return false;
    }
    
    bool is_out_of_bounds(vector2_t position, double x0, double x1, double y0, double y1) {
        return position.x < x0 || position.x > x1 || position.y < y0 || position.y > y1;
    }
    
    charge_t charge_create(double q, vector2_t pos) {
        charge_t c = {.q = q, .pos = pos};
        return c;
    }
    
    bool compute_e(charge_t c, vector2_t p, double eps, vector2_t *e) {
        *e = vector2_create_zero();
        vector2_t r = vector2_substract(c.pos, p);
        double norm_r = vector2_norm(r);
        double E_i = K * (fabs(c.q) / (norm_r * norm_r));
        *e = vector2_multiply(vector2_normalize(r), E_i);
    
        if (c.q > 0) {
            *e = vector2_multiply(*e, -1);
        }
    
        return norm_r >= eps;
    }
    
    bool compute_total_normalized_e(charge_t *charges, int num_charges, vector2_t p, double eps, vector2_t *e) {
        *e = vector2_create_zero();
    
        for (int i = 0; i < num_charges; i += 1) {
            vector2_t tmp;
            if (!compute_e(charges[i], p, eps, &tmp)) {
                return false;
            }
    
            *e = vector2_add(*e, tmp);
        }
    
        *e = vector2_normalize(*e);
        return true;
    }
    
    void draw_field_line(struct gfx_context_t *ctxt, charge_t *charges, int num_charges, double dx, vector2_t pos0, double x0, double x1, double y0, double y1) {
        vector2_t current_pos = pos0;
    
        while (true) {
            vector2_t new_pos;
    
            if (!compute_next_point(charges, num_charges, current_pos, 4.5e-2, &new_pos, dx)) {
                break;
            }
    
            if (is_out_of_bounds(new_pos, x0, x1, y0, y1)) {
                break;
            }
    
            coordinates_t current_coordinates = position_to_coordinates(SCREEN_WIDTH, SCREEN_HEIGHT, x0, x1, y0, y1, current_pos);
            coordinates_t new_coordinates = position_to_coordinates(SCREEN_WIDTH, SCREEN_HEIGHT, x0, x1, y0, y1, new_pos);
            gfx_draw_line(ctxt, current_coordinates, new_coordinates, COLOR_BLUE);
            current_pos = new_pos;
        }
    }
    
    void draw_charges(struct gfx_context_t *ctxt, charge_t *charges, int num_charges, double x0, double x1, double y0, double y1) {
        for (int32_t i = 0; i < num_charges; i += 1) {
            coordinates_t c = position_to_coordinates(SCREEN_WIDTH, SCREEN_HEIGHT, x0, x1, y0, y1, charges[i].pos);
    
            int32_t radius = 20;
            gfx_draw_circle(ctxt, c, radius, COLOR_WHITE);
    
            int32_t color = charges[i].q > 0 ? COLOR_RED : COLOR_BLUE;
            int32_t half_length = (int32_t)(radius * .6);
            gfx_draw_line(ctxt, coordinates_create(c.row, c.column - half_length), coordinates_create(c.row, c.column + half_length), color);
    
            if (charges[i].q > 0) {
                gfx_draw_line(ctxt, coordinates_create(c.row - half_length, c.column), coordinates_create(c.row + half_length, c.column), color);
            }
        }
    }