summaryrefslogtreecommitdiff
path: root/clusters.c
blob: ef80ee37f19a4eab47c7e977a885856ef7fb8467 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <time.h>
#include <stdlib.h>
#include <cairo.h>
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>

static double
sample_exp (double lambda)
{
    double u = drand48 ();

    return -log (1 - u) / lambda;
}

#define FALSE 0
#define TRUE 1

#define WIDTH 6000
#define HEIGHT 20
#define N_YEARS 10
#define DEATHS_PER_YEAR 10

#define BG_COLOR        1, 1, 1
#define CLUSTER_WIDTH   10.0
#define CLUSTER_COLOR   0.0, 0.6, 0.3, 0.4
#define LINE_WIDTH      1.0
#define LINE_COLOR      0.0, 0.0, 0.0
#define DEATH_WIDTH     1.0
#define DEATH_COLOR     0.0, 0.0, 0.0
#define DEATH_HEIGHT    (CLUSTER_WIDTH / HEIGHT)

static double *
generate_deaths (int n_years, double deaths_per_year, int *n_deaths)
{
    double w;
    double t;
    double *result = malloc (10 * sizeof (double));
    double *first;

    t = 0.0;
    *n_deaths = 0;

    w = sample_exp (deaths_per_year);
    t += w;
    while (t < n_years)
    {
        result[(*n_deaths)++] = t;
        result = realloc (result, ((*n_deaths) + 10) * sizeof (double));

        w = sample_exp (deaths_per_year);
        t += w;
    }

    return result;
}

int
main ()
{
    cairo_surface_t *surface =
        cairo_image_surface_create (CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT);
    int i;
    double t = 0.0;
    cairo_t *cr = cairo_create (surface);
    double y = HEIGHT / 2.0;
    double w;
    int n_deaths;
    int cluster;
    double *deaths;
    int in_cluster;
    double cluster_x0;

    srand48 (time (0));

    deaths = generate_deaths (N_YEARS, DEATHS_PER_YEAR, &n_deaths);
    
    cairo_set_source_rgb (cr, BG_COLOR);
    cairo_paint (cr);
    
    cairo_move_to (cr, 0.0, y);

    for (i = 1; i < n_deaths; ++i)
    {
        double d0 = deaths[i - 1];
        double d1 = deaths[i];
        double x0 = (d0 / N_YEARS) * WIDTH;
        double x1 = (d1 / N_YEARS) * WIDTH;

        cairo_set_line_width (cr, LINE_WIDTH);
        cairo_set_source_rgb (cr, LINE_COLOR);
        cairo_move_to (cr, x0, y);
        cairo_line_to (cr, x1, y);
        cairo_stroke (cr);
    }

    for (i = 0; i < n_deaths; ++i)
    {
        double d = deaths[i];
        double x = (d / N_YEARS) * WIDTH;

        cairo_set_line_width (cr, DEATH_WIDTH);
        cairo_move_to (cr, x, (0.5 - DEATH_HEIGHT / 2.0) * HEIGHT);
        cairo_line_to (cr, x, (0.5 + DEATH_HEIGHT / 2.0) * HEIGHT);
        cairo_set_source_rgb (cr, DEATH_COLOR);
        cairo_stroke (cr);
    }

    in_cluster = 0;
    for (i = 1; i < n_deaths; ++i)
    {
        double d0 = deaths[i - 1];
        double d1 = deaths[i];
        double x1 = (d1 / N_YEARS) * WIDTH;

        if (!in_cluster && d1 - d0 <= 1.0 / DEATHS_PER_YEAR)
        {
            cluster_x0 = (d0 / N_YEARS) * WIDTH;
            in_cluster = 1;
        }
        if (in_cluster && d1 - d0 > 1.0 / DEATHS_PER_YEAR)
        {
            double x1 = (d0 / N_YEARS) * WIDTH;

            cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
            cairo_move_to (cr, cluster_x0, y);
            cairo_line_to (cr, x1, y);
            cairo_set_line_width (cr, CLUSTER_WIDTH);
            cairo_set_source_rgba (cr, CLUSTER_COLOR);
            cairo_stroke (cr);

            in_cluster = 0;
        }
    }
    
    cairo_surface_write_to_png (surface, "diagram.png");

    return 0;
}