Skip to content
Snippets Groups Projects
Commit 14c9c432 authored by tanguy.cavagna's avatar tanguy.cavagna :desktop:
Browse files

Reorganised the code for better separation

parent ca82a784
Branches
No related tags found
No related merge requests found
......@@ -10,6 +10,25 @@
*/
#include "charge.h"
bool pos_contrain_in_universe(vec2 pos) {
return (pos.x <= UNIV_MAX_X && pos.x >= UNIV_MIN_X && pos.y <= UNIV_MAX_Y &&
pos.y >= UNIV_MIN_Y);
}
vec2 position_to_coordinates(int width, int height, vec2 pos) {
return vec2_create((int)round(width * (pos.x - UNIV_MIN_X)),
(int)round(height * (pos.y - UNIV_MIN_Y)));
}
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 compute_e(charge_t c, vec2 p, double eps, vec2 *e) {
vec2 qP = vec2_sub(p, c.pos);
double norm = vec2_norm(qP);
......@@ -42,7 +61,7 @@ bool compute_p_next(charge_t *charges, int num_charges, double eps,
v = vec2_div(vec2_mul(v, delta), vec2_norm(v));
// P ± deltax * E / ||E||
*p = vec2_sub(*p, vec2_mul(v, opposed ? -1 : 1));
*p = vec2_add(*p, vec2_mul(v, opposed ? -1 : 1));
return can_draw;
}
......@@ -50,99 +69,4 @@ bool compute_p_next(charge_t *charges, int num_charges, double eps,
charge_t charge_create(double q, vec2 pos) {
charge_t c = {.q = q, .pos = pos};
return c;
}
bool pos_contrain_in_universe(vec2 pos) {
return (pos.x <= UNIV_MAX_X && pos.x >= UNIV_MIN_X && pos.y <= UNIV_MAX_Y &&
pos.y >= UNIV_MIN_Y);
}
coordinates_t position_to_coordinates(int width, int height, vec2 pos) {
return coordinates_create((int)round(height * (pos.y - UNIV_MIN_Y)),
(int)round(width * (pos.x - UNIV_MIN_X)));
}
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(charge_t *charges, int num_charges, double dx, int w,
int h, vec2 p, vec2 next, bool side) {
while (pos_contrain_in_universe(next) &&
pos_not_too_close(next, charges, num_charges)) {
coordinates_t old_coord = position_to_coordinates(w, h, p);
coordinates_t p_coord = position_to_coordinates(w, h, next);
glBegin(GL_LINES);
glColor3f(255, 255, 255);
glVertex2f(p_coord.row, p_coord.column);
glVertex2f(old_coord.row, old_coord.column);
glEnd();
p = next; // Save current point
compute_p_next(charges, num_charges, EPS, dx, &next, side);
}
return true;
}
void draw_field_line(charge_t *charges, int num_charges, double dx, vec2 pos0,
int w, int h) {
vec2 pos1 = pos0;
field_line_segment(charges, num_charges, dx, w, h, pos0, pos1, true);
field_line_segment(charges, num_charges, dx, w, h, pos0, pos1, false);
}
void draw_charges(charge_t *charges, int num_charges, int w, int h) {
// Center coordinates
coordinates_t c;
// Charges coordinates
coordinates_t ch0;
coordinates_t ch1;
int chargePadding = CHARGE_RADIUS / 2;
// Draw charges
for (int i = 0; i < num_charges; i++) {
coordinates_t chCoord = position_to_coordinates(w, h, charges[i].pos);
// Draw sign according to charge value
if (charges[i].q < 0) {
glBegin(GL_LINES);
glColor3f(0, 0, 255);
glVertex2f(chCoord.row - chargePadding, chCoord.column);
glVertex2f(chCoord.row + chargePadding, chCoord.column);
glEnd();
} else {
glBegin(GL_LINES);
glColor3f(255, 0, 0);
glVertex2f(chCoord.row, chCoord.column - chargePadding);
glVertex2f(chCoord.row, chCoord.column + chargePadding);
glVertex2f(chCoord.row - chargePadding, chCoord.column);
glVertex2f(chCoord.row + chargePadding, chCoord.column);
glEnd();
}
draw_circle(chCoord, CHARGE_RADIUS, charges[i].q < 0 ? 0 : 255, 0,
charges[i].q < 0 ? 255 : 0);
}
}
void generate_points(vec2 points[], int nb_points, int w, int h) {
double x = 0;
double y = 0;
for (int i = 0; i < nb_points; i++) {
x = rand_one();
y = rand_one();
points[i] = vec2_create(x, y);
}
}
\ No newline at end of file
......@@ -11,7 +11,6 @@
#ifndef _CHARGE_H_
#define _CHARGE_H_
#include "../draw/draw.h"
#include "../utilities/utils.h"
#include "../vec2/vec2.h"
#include <GL/freeglut.h>
......@@ -34,6 +33,36 @@ typedef struct _charge_t {
vec2 pos;
} charge_t;
/**
* @brief Check whether a pos is in the universe or not
*
* @param pos
* @return true
* @return false
*/
bool pos_contrain_in_universe(vec2 pos);
/**
* @brief Convert a position ([0, 1]x[0, 1]) to a screen position
*
* @param width
* @param height
* @param pos
* @return vec2
*/
vec2 position_to_coordinates(int width, int height, vec2 pos);
/**
* @brief Check whether a position is too close to a charge or not
*
* @param p
* @param c
* @param num_charges
* @return true
* @return false
*/
bool pos_not_too_close(vec2 p, charge_t *c, int num_charges);
/**
* @brief Compute E*qP/norm(qP)
*
......@@ -82,54 +111,4 @@ bool compute_p_next(charge_t *charges, int num_charges, double eps,
*/
charge_t charge_create(double q, vec2 pos);
/**
* @brief Draw a segment of a field line between two given points
*
* @param charges All the charges
* @param num_charges Number of charges
* @param dx Distance between next point and current point
* @param w Window width
* @param h Window height
* @param p Current pos
* @param next Next pos
* @param side Side of the line
* @return true
* @return false
*/
bool field_line_segment(charge_t *charges, int num_charges, double dx, int w,
int h, vec2 p, vec2 next, bool side);
/**
* @brief Draw a field line
*
* @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 w Window width
* @param h Window height
*/
void draw_field_line(charge_t *charges, int num_charges, double dx, vec2 pos0,
int w, int h);
/**
* @brief Draw all charges
* A circle with a minus sign for negative charges
* A circle with a plus sign for positive charges
*
* @param charges All the charges
* @param num_charges Number of charges in action
* @param w Window width
* @param h Window height
*/
void draw_charges(charge_t *charges, int num_charges, int w, int h);
/**
* @brief Generate a given amount of points
*
* @param points Points array
* @param nb_points Number of point to generate
*/
void generate_points(vec2 points[], int nb_points, int w, int h);
#endif
\ No newline at end of file
......@@ -10,14 +10,17 @@
*/
#include "draw.h"
#include <math.h>
coordinates_t coordinates_create(int row_, int column_) {
coordinates_t c = {.row = row_, .column = column_};
return c;
}
void draw_circle(coordinates_t c, int rad, int r, int g, int b) {
//=====================
// PRIVATE
//=====================
/**
* @brief Draw a circle
*
* @param center
* @param rad
*/
void draw_circle(vec2 center, int rad) {
int i;
int lineAmount = 100; //# of triangles used to draw circle
......@@ -25,10 +28,73 @@ void draw_circle(coordinates_t c, int rad, int r, int g, int b) {
GLfloat twicePi = 2.0f * 3.141592;
glBegin(GL_LINE_LOOP);
glColor3f(r, g, b);
for (i = 0; i <= lineAmount; i++) {
glVertex2f(c.row + (rad * cos(i * twicePi / lineAmount)),
c.column + (rad * sin(i * twicePi / lineAmount)));
glVertex2f(center.x + (rad * cos(i * twicePi / lineAmount)),
center.y + (rad * sin(i * twicePi / lineAmount)));
}
glEnd();
}
/**
* @brief Draw a line
*
* @param start
* @param end
*/
void draw_line(vec2 start, vec2 end) {
glBegin(GL_LINES);
glVertex2f(start.x, start.y);
glVertex2f(end.x, end.y);
glEnd();
}
//=====================
// PUBLIC
//=====================
void draw_field_line_segment(charge_t *charges, int num_charges, double dx,
int w, int h, vec2 p, vec2 next, bool side) {
while (pos_contrain_in_universe(next) &&
pos_not_too_close(next, charges, num_charges)) {
vec2 old_coord = position_to_coordinates(w, h, p);
vec2 p_coord = position_to_coordinates(w, h, next);
glColor3f(255, 255, 255);
draw_line((vec2){p_coord.x, p_coord.y},
(vec2){old_coord.x, old_coord.y});
p = next; // Save current point
compute_p_next(charges, num_charges, EPS, dx, &next, side);
}
}
void draw_field_line(charge_t *charges, int num_charges, double dx, vec2 pos0,
int w, int h) {
vec2 pos1 = pos0;
draw_field_line_segment(charges, num_charges, dx, w, h, pos0, pos1, true);
draw_field_line_segment(charges, num_charges, dx, w, h, pos0, pos1, false);
}
void draw_charges(charge_t *charges, int num_charges, int w, int h) {
int chargePadding = CHARGE_RADIUS / 2;
// Draw charges
for (int i = 0; i < num_charges; i++) {
vec2 chCoord = position_to_coordinates(w, h, charges[i].pos);
// Draw sign according to charge value
if (charges[i].q < 0) {
glColor3f(0, 0, 255);
draw_line((vec2){chCoord.x - chargePadding, chCoord.y},
(vec2){chCoord.x + chargePadding, chCoord.y});
} else {
glColor3f(255, 0, 0);
draw_line((vec2){chCoord.x, chCoord.y - chargePadding},
(vec2){chCoord.x, chCoord.y + chargePadding});
draw_line((vec2){chCoord.x - chargePadding, chCoord.y},
(vec2){chCoord.x + chargePadding, chCoord.y});
}
draw_circle(chCoord, CHARGE_RADIUS);
}
}
\ No newline at end of file
......@@ -12,25 +12,53 @@
#ifndef _DRAW_H_
#define _DRAW_H_
#include "../charge/charge.h"
#include "../vec2/vec2.h"
#include <GL/freeglut.h>
#include <GL/gl.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
uint32_t row;
uint32_t column;
} coordinates_t;
/**
* @brief Create a coordinate
* @brief Draw a segment of a field line between two given points
*
* @param row_ Row number
* @param column_ Column number
* @return coordinates_t
* @param charges All the charges
* @param num_charges Number of charges
* @param dx Distance between next point and current point
* @param w Window width
* @param h Window height
* @param p Current pos
* @param next Next pos
* @param side Side of the line
*/
coordinates_t coordinates_create(int row_, int column_);
void draw_field_line_segment(charge_t *charges, int num_charges, double dx,
int w, int h, vec2 p, vec2 next, bool side);
void draw_circle(coordinates_t c, int radius, int r, int g, int b);
/**
* @brief Draw a field line
*
* @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 w Window width
* @param h Window height
*/
void draw_field_line(charge_t *charges, int num_charges, double dx, vec2 pos0,
int w, int h);
/**
* @brief Draw all charges
* A circle with a minus sign for negative charges
* A circle with a plus sign for positive charges
*
* @param charges All the charges
* @param num_charges Number of charges in action
* @param w Window width
* @param h Window height
*/
void draw_charges(charge_t *charges, int num_charges, int w, int h);
#endif
......@@ -9,6 +9,7 @@
*
*/
#include "charge/charge.h"
#include "draw/draw.h"
#include "utilities/utils.h"
#include <GL/freeglut.h>
#include <GL/glut.h>
......@@ -22,11 +23,31 @@
#define WINDOW_HEIGHT 500
#define NB_CHARGES 5
#define NB_POINTS 200
#define MAXIMUM_CHARGES 30 // Can be replace by a dynamic array
#define DELTA (1 / sqrt(pow(WINDOW_WIDTH, 2) + pow(WINDOW_HEIGHT, 2)))
int charge_count = NB_CHARGES;
vec2 pos[30];
double chs[30];
vec2 starting_points[NB_POINTS];
vec2 default_charges_pos[MAXIMUM_CHARGES];
double default_charges[MAXIMUM_CHARGES];
/**
* @brief Generate a given set of points in the [0, 1]x[0, 1] universe
*
* @param points
* @param nb_points
*/
void generate_points(vec2 points[], int nb_points) {
double x = 0;
double y = 0;
for (int i = 0; i < nb_points; i++) {
x = rand_one();
y = rand_one();
points[i] = vec2_create(x, y);
}
}
/**
* @brief Display function of Glut
......@@ -39,16 +60,13 @@ void display() {
// Generate all the charges
charge_t charges[charge_count];
for (int i = 0; i < charge_count; i++)
charges[i] = charge_create(chs[i], pos[i]);
charges[i] = charge_create(default_charges[i], default_charges_pos[i]);
draw_charges(charges, charge_count, WINDOW_WIDTH, WINDOW_HEIGHT);
// Generate all the points
vec2 points[NB_POINTS];
generate_points(points, NB_POINTS, WINDOW_WIDTH, WINDOW_HEIGHT);
for (int i = 0; i < NB_POINTS; i++) {
draw_field_line(charges, charge_count, DELTA, points[i], WINDOW_WIDTH,
WINDOW_HEIGHT);
draw_field_line(charges, charge_count, DELTA, starting_points[i],
WINDOW_WIDTH, WINDOW_HEIGHT);
}
glutSwapBuffers();
......@@ -68,9 +86,9 @@ void handle_mouse_input(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON) {
charge_count += 1;
pos[charge_count - 1] =
vec2_create((double)y / WINDOW_WIDTH, (double)x / WINDOW_HEIGHT);
chs[charge_count - 1] = rand_one() / (rand_one() * 10 - 5);
default_charges_pos[charge_count - 1] =
vec2_create((double)x / WINDOW_WIDTH, (double)y / WINDOW_HEIGHT);
default_charges[charge_count - 1] = rand_one() / (rand_one() * 10 - 5);
}
glutPostRedisplay();
......@@ -86,11 +104,16 @@ void handle_mouse_input(int button, int state, int x, int y) {
int main(int argc, char **argv) {
srand(time(NULL));
// Generate all default charges
for (int i = 0; i < charge_count; i++) {
chs[i] = rand_one() / (rand_one() * 10 - 5);
pos[i] = vec2_create(rand_one(), rand_one());
default_charges[i] = rand_one() / (rand_one() * 10 - 5);
default_charges_pos[i] = vec2_create(rand_one(), rand_one());
}
// Generate all field lines starting points
generate_points(starting_points, NB_POINTS);
// Window initialization
glutInit(&argc, argv);
glutSetOption(GLUT_MULTISAMPLE, 16);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH |
......@@ -108,6 +131,7 @@ int main(int argc, char **argv) {
glutMainLoop();
// Object destroy
glutDestroyWindow(window);
return EXIT_SUCCESS;
}
\ No newline at end of file
#ifndef _UTILS_H_
#define _UTILS_H_
#include "../draw/draw.h"
#include "../vec2/vec2.h"
#include <stdint.h>
#include <stdlib.h>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment