2 // Written and (C) by Francois Fleuret
3 // Contact <francois.fleuret@idiap.ch> for comments & bug reports
7 Plotter::Plotter(int width, int height, int scaling) {
9 _width = width * _scaling;
10 _height = height * _scaling;
12 _tag_map = new Tag *[_width * _height];
13 _tag_stack = new Tag[_width * _height];
15 _red_imap = new scalar_t[(_width + 1) * (_height + 1)];
16 _green_imap = new scalar_t[(_width + 1) * (_height + 1)];
17 _blue_imap = new scalar_t[(_width + 1) * (_height + 1)];
30 void Plotter::reset() {
31 for(int k = 0; k < _width * _height; k++) {
34 _tag_stack_top = _tag_stack;
38 void Plotter::draw_polygon(Polygon *p) {
39 int nb = p->_nb_vertices;
43 for(int n = 0; n < nb; n++) {
44 ix[n] = int(p->_x[n] * scalar_t(_scaling) + 0.5);
45 iy[n] = int(p->_y[n] * scalar_t(_scaling) + 0.5);
48 scalar_t red = p->_red;
49 scalar_t green = p->_green;
50 scalar_t blue = p->_blue;
54 if(iy[0] > iy[nb-1]) direction = 1;
55 else if(iy[0] < iy[nb-1]) direction = -1;
58 for(int n = 0; n < nb; n++) {
61 if(ix[n] >= 0 && ix[n] < _width && iy[n] >= 0 && iy[n] < _height &&
62 ix[m] >= 0 && ix[m] < _width && iy[m] >= 0 && iy[m] < _height) {
64 if(iy[m] > iy[n]) { // RIGHT BORDERS
67 push_tag(1 + ix[n], iy[n], red, green, blue);
70 for(int y = iy[n] + 1; y <= iy[m]; y++) {
71 push_tag(1 + ix[n] + ((ix[m] - ix[n]) * (y - iy[n]))/(iy[m] - iy[n]), y,
77 } else if(iy[m] < iy[n]) { // LEFT BORDERS
80 push_tag(ix[n], iy[n], red, green, blue);
83 for(int y = iy[n] - 1; y >= iy[m]; y--) {
84 push_tag(ix[n] + ((ix[m] - ix[n]) * (y - iy[n]))/(iy[m] - iy[n]), y,
92 if(direction >= 0) push_tag(ix[n]+1, iy[n], red, green, blue);
93 push_tag(ix[m], iy[m], red, green, blue);
100 if(iy[m] > iy[n]) { // RIGHT BORDERS
103 protected_push_tag(1 + ix[n], iy[n], red, green, blue);
106 for(int y = iy[n] + 1; y <= iy[m]; y++) {
107 protected_push_tag(1 + ix[n] + ((ix[m] - ix[n]) * (y - iy[n]))/(iy[m] - iy[n]), y,
113 } else if(iy[m] < iy[n]) { // LEFT BORDERS
116 protected_push_tag(ix[n], iy[n], red, green, blue);
119 for(int y = iy[n] - 1; y >= iy[m]; y--) {
120 protected_push_tag(ix[n] + ((ix[m] - ix[n]) * (y - iy[n]))/(iy[m] - iy[n]), y,
129 protected_push_tag(ix[n]+1, iy[n], red, green, blue);
132 protected_push_tag(ix[m], iy[m], red, green, blue);
142 void Plotter::fill() {
143 bool in[_current_polygon];
144 for(int p = 0; p < _current_polygon; p++) in[p] = false;
146 scalar_t red[_current_polygon], green[_current_polygon], blue[_current_polygon];
151 for(int x = 0; x < _width+1; x++) {
158 int current_index = -1;
159 for(int y = 0; y < _height; y++) {
160 scalar_t sred = 0, sgreen = 0, sblue = 0;
166 for(int x = 0; x < _width; x++) {
167 for(Tag *t = *u; t; t = t->next) {
169 in[t->index] = false;
170 if(t->index == current_index) {
172 while(current_index >= 0 && !in[current_index]) current_index--;
176 red[t->index] = t->red;
177 green[t->index] = t->green;
178 blue[t->index] = t->blue;
179 if(t->index > current_index) current_index = t->index;
183 if(current_index >= 0) {
184 sred += red[current_index];
185 sgreen += green[current_index];
186 sblue += blue[current_index];
189 _red_imap[k] = sred + _red_imap[lk];
190 _green_imap[k] = sgreen + _green_imap[lk];
191 _blue_imap[k] = sblue + _blue_imap[lk];
199 void Plotter::save_as_ppm(Universe *universe, const char *filename, int downscale) {
201 for(int p = 0; p < universe->_nb_polygons; p++) {
202 if(universe->_polygons[p]) {
203 draw_polygon(universe->_polygons[p]);
208 unsigned char *image = new unsigned char[(_width/downscale) * (_height/downscale) * 3];
211 for(int y = 0; y < _height / downscale; y++) {
212 for(int x = 0; x < _width / downscale; x++) {
213 image[n++] = int(255 * red_sum(x * downscale, y * downscale, (x + 1) * downscale, (y + 1) * downscale) / scalar_t(downscale * downscale));
214 image[n++] = int(255 * green_sum(x * downscale, y * downscale, (x + 1) * downscale, (y + 1) * downscale) / scalar_t(downscale * downscale));
215 image[n++] = int(255 * blue_sum(x * downscale, y * downscale, (x + 1) * downscale, (y + 1) * downscale) / scalar_t(downscale * downscale));
219 ofstream out(filename);
221 out << _width/downscale << " " << _height/downscale << endl;
223 out.write((char *) image, (_width/downscale) * (_height/downscale) * 3);