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 @@ ...@@ -10,6 +10,25 @@
*/ */
#include "charge.h" #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) { bool compute_e(charge_t c, vec2 p, double eps, vec2 *e) {
vec2 qP = vec2_sub(p, c.pos); vec2 qP = vec2_sub(p, c.pos);
double norm = vec2_norm(qP); double norm = vec2_norm(qP);
...@@ -42,7 +61,7 @@ bool compute_p_next(charge_t *charges, int num_charges, double eps, ...@@ -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)); v = vec2_div(vec2_mul(v, delta), vec2_norm(v));
// P ± deltax * E / ||E|| // 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; return can_draw;
} }
...@@ -50,99 +69,4 @@ bool compute_p_next(charge_t *charges, int num_charges, double eps, ...@@ -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 charge_create(double q, vec2 pos) {
charge_t c = {.q = q, .pos = pos}; charge_t c = {.q = q, .pos = pos};
return c; 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 @@ ...@@ -11,7 +11,6 @@
#ifndef _CHARGE_H_ #ifndef _CHARGE_H_
#define _CHARGE_H_ #define _CHARGE_H_
#include "../draw/draw.h"
#include "../utilities/utils.h" #include "../utilities/utils.h"
#include "../vec2/vec2.h" #include "../vec2/vec2.h"
#include <GL/freeglut.h> #include <GL/freeglut.h>
...@@ -34,6 +33,36 @@ typedef struct _charge_t { ...@@ -34,6 +33,36 @@ typedef struct _charge_t {
vec2 pos; vec2 pos;
} charge_t; } 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) * @brief Compute E*qP/norm(qP)
* *
...@@ -82,54 +111,4 @@ bool compute_p_next(charge_t *charges, int num_charges, double eps, ...@@ -82,54 +111,4 @@ bool compute_p_next(charge_t *charges, int num_charges, double eps,
*/ */
charge_t charge_create(double q, vec2 pos); 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 #endif
\ No newline at end of file
...@@ -10,14 +10,17 @@ ...@@ -10,14 +10,17 @@
*/ */
#include "draw.h" #include "draw.h"
#include <math.h>
coordinates_t coordinates_create(int row_, int column_) { //=====================
coordinates_t c = {.row = row_, .column = column_}; // PRIVATE
return c; //=====================
} /**
* @brief Draw a circle
void draw_circle(coordinates_t c, int rad, int r, int g, int b) { *
* @param center
* @param rad
*/
void draw_circle(vec2 center, int rad) {
int i; int i;
int lineAmount = 100; //# of triangles used to draw circle 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) { ...@@ -25,10 +28,73 @@ void draw_circle(coordinates_t c, int rad, int r, int g, int b) {
GLfloat twicePi = 2.0f * 3.141592; GLfloat twicePi = 2.0f * 3.141592;
glBegin(GL_LINE_LOOP); glBegin(GL_LINE_LOOP);
glColor3f(r, g, b);
for (i = 0; i <= lineAmount; i++) { for (i = 0; i <= lineAmount; i++) {
glVertex2f(c.row + (rad * cos(i * twicePi / lineAmount)), glVertex2f(center.x + (rad * cos(i * twicePi / lineAmount)),
c.column + (rad * sin(i * twicePi / lineAmount))); center.y + (rad * sin(i * twicePi / lineAmount)));
} }
glEnd(); 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 @@ ...@@ -12,25 +12,53 @@
#ifndef _DRAW_H_ #ifndef _DRAW_H_
#define _DRAW_H_ #define _DRAW_H_
#include "../charge/charge.h"
#include "../vec2/vec2.h"
#include <GL/freeglut.h> #include <GL/freeglut.h>
#include <GL/gl.h> #include <GL/gl.h>
#include <math.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.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 charges All the charges
* @param column_ Column number * @param num_charges Number of charges
* @return coordinates_t * @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 #endif
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* *
*/ */
#include "charge/charge.h" #include "charge/charge.h"
#include "draw/draw.h"
#include "utilities/utils.h" #include "utilities/utils.h"
#include <GL/freeglut.h> #include <GL/freeglut.h>
#include <GL/glut.h> #include <GL/glut.h>
...@@ -22,11 +23,31 @@ ...@@ -22,11 +23,31 @@
#define WINDOW_HEIGHT 500 #define WINDOW_HEIGHT 500
#define NB_CHARGES 5 #define NB_CHARGES 5
#define NB_POINTS 200 #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))) #define DELTA (1 / sqrt(pow(WINDOW_WIDTH, 2) + pow(WINDOW_HEIGHT, 2)))
int charge_count = NB_CHARGES; int charge_count = NB_CHARGES;
vec2 pos[30]; vec2 starting_points[NB_POINTS];
double chs[30]; 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 * @brief Display function of Glut
...@@ -39,16 +60,13 @@ void display() { ...@@ -39,16 +60,13 @@ void display() {
// Generate all the charges // Generate all the charges
charge_t charges[charge_count]; charge_t charges[charge_count];
for (int i = 0; i < charge_count; i++) 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); 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++) { for (int i = 0; i < NB_POINTS; i++) {
draw_field_line(charges, charge_count, DELTA, points[i], WINDOW_WIDTH, draw_field_line(charges, charge_count, DELTA, starting_points[i],
WINDOW_HEIGHT); WINDOW_WIDTH, WINDOW_HEIGHT);
} }
glutSwapBuffers(); glutSwapBuffers();
...@@ -68,9 +86,9 @@ void handle_mouse_input(int button, int state, int x, int y) { ...@@ -68,9 +86,9 @@ void handle_mouse_input(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON) { if (button == GLUT_LEFT_BUTTON) {
charge_count += 1; charge_count += 1;
pos[charge_count - 1] = default_charges_pos[charge_count - 1] =
vec2_create((double)y / WINDOW_WIDTH, (double)x / WINDOW_HEIGHT); vec2_create((double)x / WINDOW_WIDTH, (double)y / WINDOW_HEIGHT);
chs[charge_count - 1] = rand_one() / (rand_one() * 10 - 5); default_charges[charge_count - 1] = rand_one() / (rand_one() * 10 - 5);
} }
glutPostRedisplay(); glutPostRedisplay();
...@@ -86,11 +104,16 @@ void handle_mouse_input(int button, int state, int x, int y) { ...@@ -86,11 +104,16 @@ void handle_mouse_input(int button, int state, int x, int y) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
srand(time(NULL)); srand(time(NULL));
// Generate all default charges
for (int i = 0; i < charge_count; i++) { for (int i = 0; i < charge_count; i++) {
chs[i] = rand_one() / (rand_one() * 10 - 5); default_charges[i] = rand_one() / (rand_one() * 10 - 5);
pos[i] = vec2_create(rand_one(), rand_one()); 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); glutInit(&argc, argv);
glutSetOption(GLUT_MULTISAMPLE, 16); glutSetOption(GLUT_MULTISAMPLE, 16);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH |
...@@ -108,6 +131,7 @@ int main(int argc, char **argv) { ...@@ -108,6 +131,7 @@ int main(int argc, char **argv) {
glutMainLoop(); glutMainLoop();
// Object destroy
glutDestroyWindow(window); glutDestroyWindow(window);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
\ No newline at end of file
#ifndef _UTILS_H_ #ifndef _UTILS_H_
#define _UTILS_H_ #define _UTILS_H_
#include "../draw/draw.h"
#include "../vec2/vec2.h"
#include <stdint.h> #include <stdint.h>
#include <stdlib.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