diff --git a/charge/charge.h b/charge/charge.h
index 1f8343717814a685a99dd785be0f2424e8119a63..097fe21859857c0fa949941563d4d0b62aa85d35 100644
--- a/charge/charge.h
+++ b/charge/charge.h
@@ -16,6 +16,7 @@
 #include <math.h>
 #include <stdbool.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 
 #define K 8.988e9
diff --git a/draw/draw.c b/draw/draw.c
index e372aed509f8c600fe4b5ea45697d453949a5213..e178166fbee66f348d743a45036523ef11c9e2a3 100644
--- a/draw/draw.c
+++ b/draw/draw.c
@@ -48,6 +48,19 @@ void draw_line(vec2 start, vec2 end) {
     glEnd();
 }
 
+void get_heatmap_color(double value, double *red, double *green, double *blue) {
+    double aR = 0.0;
+    double aG = 0.0;
+    double aB = 0.0; // RGB for our 1st color (blue in this case).
+    double bR = 0.31;
+    double bG = 0.23;
+    double bB = 0.31; // RGB for our 2nd color (red in this case).
+
+    *red = (bR - aR) * value + aR;   // Evaluated as -255*value + 255.
+    *green = (bG - aG) * value + aG; // Evaluates as 0.
+    *blue = (bB - aB) * value + aB;  // Evaluates as 255*value + 0.
+}
+
 //=====================
 //      PUBLIC
 //=====================
@@ -66,7 +79,7 @@ void draw_textbox(vec2 pos, char *text) {
     glEnd();
 
     glBegin(GL_LINE_LOOP);
-    glColor3f(255, 255, 255);
+    glColor3f(1, 1, 1);
     glVertex2d(pos.x, pos.y);
     glVertex2d(pos.x + textbox_width, pos.y);
     glVertex2d(pos.x + textbox_width, pos.y + textbox_height);
@@ -74,7 +87,7 @@ void draw_textbox(vec2 pos, char *text) {
     glEnd();
 
     // Text
-    glColor3f(255, 255, 255);
+    glColor3f(1, 1, 1);
     glRasterPos2i(pos.x + 4, pos.y + CHAR_HEIGHT);
     glutBitmapString(GLUT_BITMAP_8_BY_13, (unsigned char *)text);
 }
@@ -86,7 +99,6 @@ void draw_field_line_segment(charge_t *charges, int num_charges, double dx,
         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});
 
@@ -103,6 +115,70 @@ void draw_field_line(charge_t *charges, int num_charges, double dx, vec2 pos0,
     draw_field_line_segment(charges, num_charges, dx, w, h, pos0, pos1, false);
 }
 
+void draw_heatmap(charge_t *charges, int num_charges, int w, int h) {
+    vec2 *intensities = malloc(sizeof(vec2) * (w * h));
+    double min = DBL_MAX, max = 0;
+
+    int i = 0;
+    for (double y = 0; y < 1.0 - 1.0 / h; y += 1.0 / h) {
+        for (double x = 0; x < 1.0 - 1.0 / w; x += 1.0 / w) {
+            vec2 p = vec2_create(x, y);
+            compute_total_normalized_e(charges, num_charges, p, EPS,
+                                       &intensities[i]);
+
+            double in = vec2_norm(intensities[i]);
+            if (in < min && in > 1)
+                min = in;
+            if (in > max)
+                max = in;
+
+            i++;
+        }
+    }
+
+    for (int i = 0; i < h * w; i++) {
+        int x = i % w;
+        int y = i / w;
+        double r, g, b;
+        double a = (vec2_norm(intensities[i]) / max) * 20.0;
+
+        get_heatmap_color(a, &r, &g, &b);
+        glBegin(GL_POINTS);
+        glColor3f(r, g, b);
+        glVertex2d(x, y);
+        glEnd();
+    }
+
+    free(intensities);
+}
+
+void draw_vector_field(charge_t *charges, int num_charges, vec2 *points,
+                       int nb_points, int w, int h) {
+    double min = DBL_MAX, max = 0.0;
+    vec2 vs[nb_points];
+    for (int i = 0; i < nb_points; i++) {
+        compute_total_normalized_e(charges, num_charges, points[i], EPS,
+                                   &vs[i]);
+
+        double in = vec2_norm(vs[i]);
+        if (in < min && in > 1)
+            min = in;
+        if (in > max)
+            max = in;
+    }
+
+    for (int i = 0; i < nb_points; i++) {
+        vec2 a = position_to_coordinates(w, h, points[i]);
+
+        glBegin(GL_LINES);
+        glColor3f(0.61, 0.87, 0.61);
+        glVertex2d(a.x, a.y);
+        a = vec2_add(a, vec2_mul(vec2_div(vs[i], max), 10));
+        glVertex2d(a.x, a.y);
+        glEnd();
+    }
+}
+
 void draw_charges(charge_t *charges, int num_charges, int w, int h) {
     int chargePadding = CHARGE_RADIUS / 2;
 
@@ -112,11 +188,11 @@ void draw_charges(charge_t *charges, int num_charges, int w, int h) {
 
         // Draw sign according to charge value
         if (charges[i].q < 0) {
-            glColor3f(0, 0, 255);
+            glColor3f(0.54, 0.82, 0.90);
             draw_line((vec2){chCoord.x - chargePadding, chCoord.y},
                       (vec2){chCoord.x + chargePadding, chCoord.y});
         } else {
-            glColor3f(255, 0, 0);
+            glColor3f(1, 0.4, 0.38);
             draw_line((vec2){chCoord.x, chCoord.y - chargePadding},
                       (vec2){chCoord.x, chCoord.y + chargePadding});
             draw_line((vec2){chCoord.x - chargePadding, chCoord.y},
diff --git a/draw/draw.h b/draw/draw.h
index 616bc886952583893bbc2f5d822e436951a44def..57c42642bd7779711b45ceaf66d43ede9eabf6be 100644
--- a/draw/draw.h
+++ b/draw/draw.h
@@ -16,6 +16,7 @@
 #include "../vec2/vec2.h"
 #include <GL/freeglut.h>
 #include <GL/gl.h>
+#include <float.h>
 #include <math.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -61,6 +62,29 @@ void draw_field_line_segment(charge_t *charges, int num_charges, double dx,
 void draw_field_line(charge_t *charges, int num_charges, double dx, vec2 pos0,
                      int w, int h);
 
+/**
+ * @brief Draw a heatmap of the intensity
+ *
+ * @param charges
+ * @param num_charges
+ * @param w
+ * @param h
+ */
+void draw_heatmap(charge_t *charges, int num_charges, int w, int h);
+
+/**
+ * @brief Draw a vector field
+ *
+ * @param charges
+ * @param num_charges
+ * @param points
+ * @param nb_points
+ * @param w
+ * @param h
+ */
+void draw_vector_field(charge_t *charges, int num_charges, vec2 *points,
+                       int nb_points, int w, int h);
+
 /**
  * @brief Draw all charges
  *        A circle with a minus sign for negative charges
diff --git a/main.c b/main.c
index 9373cabd5d90026968c6020f9731188b3fd3ea92..ae82fc98583f96190a75a6afb2faae1c5aef18fa 100644
--- a/main.c
+++ b/main.c
@@ -19,10 +19,22 @@
 #include <stdlib.h>
 #include <time.h>
 
+// https://stackoverflow.com/questions/3417837/what-is-the-best-way-to-suppress-a-unused-variable-x-warning
+#ifdef UNUSED
+#elif defined(__GNUC__)
+#define UNUSED(x) UNUSED_##x __attribute__((unused))
+#elif defined(__LCLINT__)
+#define UNUSED(x) /*@unused@*/ x
+#else
+#define UNUSED(x) x
+#endif
+
 #define WINDOW_WIDTH 800
 #define WINDOW_HEIGHT 800
 #define NB_CHARGES 5
-#define NB_POINTS 200
+#define GRID_SPACING 10
+#define NB_POINTS                                                              \
+    ((WINDOW_WIDTH / GRID_SPACING) * (WINDOW_WIDTH / GRID_SPACING))
 #define MAXIMUM_CHARGES 30 // Can be replace by a dynamic array
 #define DELTA (1 / sqrt(pow(WINDOW_WIDTH, 2) + pow(WINDOW_HEIGHT, 2)))
 
@@ -31,21 +43,24 @@ vec2 starting_points[NB_POINTS];
 vec2 default_charges_pos[MAXIMUM_CHARGES];
 double default_charges[MAXIMUM_CHARGES];
 
+bool toggle_lines_view = true;
+bool toggle_vector_view = false;
+bool toggle_heatmap_view = false;
+
 /**
- * @brief Generate a given set of points in the [0, 1]x[0, 1] universe
+ * @brief Generate a grid of points
  *
  * @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);
+void generate_points(vec2 points[]) {
+    int i = 0;
+
+    for (int y = 0; y < WINDOW_HEIGHT; y += GRID_SPACING) {
+        for (int x = 0; x < WINDOW_WIDTH; x += GRID_SPACING) {
+            points[i] = vec2_create(x / (double)WINDOW_WIDTH,
+                                    y / (double)WINDOW_HEIGHT);
+            i++;
+        }
     }
 }
 
@@ -62,9 +77,20 @@ void display() {
     for (int i = 0; i < charge_count; i++)
         charges[i] = charge_create(default_charges[i], default_charges_pos[i]);
 
-    for (int i = 0; i < NB_POINTS; i++) {
-        draw_field_line(charges, charge_count, DELTA, starting_points[i],
-                        WINDOW_WIDTH, WINDOW_HEIGHT);
+    if (toggle_heatmap_view)
+        draw_heatmap(charges, charge_count, WINDOW_WIDTH, WINDOW_HEIGHT);
+
+    if (toggle_lines_view) {
+        for (int i = 0; i < NB_POINTS; i += 10) {
+            glColor3f(0.2, 0.2, 0.2);
+            draw_field_line(charges, charge_count, DELTA, starting_points[i],
+                            WINDOW_WIDTH, WINDOW_HEIGHT);
+        }
+    }
+
+    if (toggle_vector_view) {
+        draw_vector_field(charges, charge_count, starting_points, NB_POINTS,
+                          WINDOW_WIDTH, WINDOW_HEIGHT);
     }
 
     draw_charges(charges, charge_count, WINDOW_WIDTH, WINDOW_HEIGHT);
@@ -99,6 +125,29 @@ void handle_mouse_input(int button, int state, int x, int y) {
     glutPostRedisplay();
 }
 
+/**
+ * @brief Toggle some views
+ *
+ * @param key
+ * @param x
+ * @param y
+ */
+void keyboard(unsigned char key, int UNUSED(x), int UNUSED(y)) {
+    switch (key) {
+    case 'l':
+        toggle_lines_view = !toggle_lines_view;
+        break;
+    case 'v':
+        toggle_vector_view = !toggle_vector_view;
+        break;
+    case 'h':
+        toggle_heatmap_view = !toggle_heatmap_view;
+        break;
+    }
+
+    glutPostRedisplay();
+}
+
 /**
  * @brief Main function
  *
@@ -116,7 +165,7 @@ int main(int argc, char **argv) {
     }
 
     // Generate all field lines starting points
-    generate_points(starting_points, NB_POINTS);
+    generate_points(starting_points);
 
     // Window initialization
     glutInit(&argc, argv);
@@ -133,6 +182,7 @@ int main(int argc, char **argv) {
 
     glutDisplayFunc(display);
     glutMouseFunc(handle_mouse_input);
+    glutKeyboardFunc(keyboard);
 
     glutMainLoop();