main: main.o misc.o \
simple_window.o \
universe.o \
+ plotter.o \
polygon.o \
xfig_tracer.o \
+ canvas.o canvas_cairo.o \
map.o \
task.o \
retina.o \
$(CXX) $(CXXFLAGS) -shared -Wl,-soname,$@ -o $@ $^
Makefile.depend: *.h *.cc Makefile
- $(CC) -M *.cc > Makefile.depend
+ $(CC) $(CXXFLAGS) -M *.cc > Makefile.depend
clean:
\rm -f main *.o *.so Makefile.depend
#include "retina.h"
#include "manipulator.h"
#include "intelligence.h"
-#include "xfig_tracer.h"
-
-#ifdef CAIRO_SUPPORT
-#include <cairo.h>
+#include "canvas_cairo.h"
-static cairo_status_t write_cairo_to_file(void *closure,
- const unsigned char *data,
- unsigned int length) {
- fwrite(data, 1, length, (FILE *) closure);
- return CAIRO_STATUS_SUCCESS;
-}
+#include "xfig_tracer.h"
void generate_png(Universe *universe, scalar_t scale, FILE *file) {
- const int depth = 4;
- const int width = int(universe->width() * scale);
- const int height = int(universe->height() * scale);
-
- cairo_surface_t *image;
- cairo_t* context_resource;
- unsigned char *data;
-
- data = new unsigned char [width * height * depth];
-
- image = cairo_image_surface_create_for_data(data,
- CAIRO_FORMAT_RGB24,
- width,
- height,
- width * depth);
-
- context_resource = cairo_create(image);
-
- cairo_scale(context_resource, scale, scale);
-
- cairo_set_source_rgb(context_resource, 1.0, 1.0, 1.0);
-
- cairo_rectangle(context_resource, 0, 0,
- universe->width(), universe->height());
-
- cairo_fill(context_resource);
-
- universe->draw(context_resource);
-
- cairo_surface_write_to_png_stream(image, write_cairo_to_file, file);
-
- cairo_destroy(context_resource);
- cairo_surface_destroy(image);
-
- delete[] data;
+ CanvasCairo canvas(scale, universe->width(), universe->height());
+ universe->draw(&canvas);
+ canvas.write_png(file);
}
-#endif
// To train
// ./main --task hit_shape.task 0 --action-mode=random --nb-ticks=5000 --proportion-for-training=0.5 --save-file=dump.mem --no-window
int window_main_fd = -1;
#ifdef CAIRO_SUPPORT
- cairo_t *window_main_cairo_cr = 0;
+ // cairo_t *window_main_cairo_cr = 0;
#endif
MapConcatener sensory_map(2);
window_main_fd = window_main->file_descriptor();
window_main->map();
#ifdef CAIRO_SUPPORT
- window_main_cairo_cr = window_main->get_cairo_context_resource();
+ // window_main_cairo_cr = window_main->get_cairo_context_resource();
#endif
cout << "When the main window has the focus, press `q' to quit and click and drag to move" << endl
<< "objects." << endl;
window_main->color(1.0, 1.0, 1.0);
window_main->fill();
-#ifdef CAIRO_SUPPORT
- universe.draw(window_main_cairo_cr);
-#else
+// #ifdef CAIRO_SUPPORT
+ // CanvasCairo cc;
+ // cc._context_resource = window_main_cairo_cr;
+ // universe.draw(&cc);
+// #else
universe.draw(window_main);
-#endif
+// #endif
task->draw(window_main);
manipulator.draw_on_universe(window_main);
--- /dev/null
+
+// Written and (C) by Francois Fleuret
+// Contact <francois.fleuret@idiap.ch> for comments & bug reports
+
+#include "plotter.h"
+
+Plotter::Plotter(int width, int height, int scaling) {
+ _scaling = scaling;
+ _width = width * _scaling;
+ _height = height * _scaling;
+
+ _tag_map = new Tag *[_width * _height];
+ _tag_stack = new Tag[_width * _height];
+
+ _red_imap = new scalar_t[(_width + 1) * (_height + 1)];
+ _green_imap = new scalar_t[(_width + 1) * (_height + 1)];
+ _blue_imap = new scalar_t[(_width + 1) * (_height + 1)];
+
+ reset();
+}
+
+Plotter::~Plotter() {
+ delete[] _tag_map;
+ delete[] _tag_stack;
+ delete[] _red_imap;
+ delete[] _green_imap;
+ delete[] _blue_imap;
+}
+
+void Plotter::reset() {
+ for(int k = 0; k < _width * _height; k++) {
+ _tag_map[k] = 0;
+ }
+ _tag_stack_top = _tag_stack;
+ _current_polygon = 0;
+}
+
+void Plotter::draw_polygon(Polygon *p) {
+ int nb = p->_nb_vertices;
+
+ int ix[nb], iy[nb];
+
+ for(int n = 0; n < nb; n++) {
+ ix[n] = int(p->_x[n] * scalar_t(_scaling) + 0.5);
+ iy[n] = int(p->_y[n] * scalar_t(_scaling) + 0.5);
+ }
+
+ scalar_t red = p->_red;
+ scalar_t green = p->_green;
+ scalar_t blue = p->_blue;
+
+ int direction;
+
+ if(iy[0] > iy[nb-1]) direction = 1;
+ else if(iy[0] < iy[nb-1]) direction = -1;
+ else direction = 0;
+
+ for(int n = 0; n < nb; n++) {
+ int m = (n+1)%nb;
+
+ if(ix[n] >= 0 && ix[n] < _width && iy[n] >= 0 && iy[n] < _height &&
+ ix[m] >= 0 && ix[m] < _width && iy[m] >= 0 && iy[m] < _height) {
+
+ if(iy[m] > iy[n]) { // RIGHT BORDERS
+
+ if(direction < 0) {
+ push_tag(1 + ix[n], iy[n], red, green, blue);
+ }
+
+ for(int y = iy[n] + 1; y <= iy[m]; y++) {
+ push_tag(1 + ix[n] + ((ix[m] - ix[n]) * (y - iy[n]))/(iy[m] - iy[n]), y,
+ red, green, blue);
+ }
+
+ direction = 1;
+
+ } else if(iy[m] < iy[n]) { // LEFT BORDERS
+
+ if(direction >= 0) {
+ push_tag(ix[n], iy[n], red, green, blue);
+ }
+
+ for(int y = iy[n] - 1; y >= iy[m]; y--) {
+ push_tag(ix[n] + ((ix[m] - ix[n]) * (y - iy[n]))/(iy[m] - iy[n]), y,
+ red, green, blue);
+ }
+
+ direction = -1;
+
+ } else {
+
+ if(direction >= 0) push_tag(ix[n]+1, iy[n], red, green, blue);
+ push_tag(ix[m], iy[m], red, green, blue);
+ direction = 0;
+
+ }
+
+ } else {
+
+ if(iy[m] > iy[n]) { // RIGHT BORDERS
+
+ if(direction < 0) {
+ protected_push_tag(1 + ix[n], iy[n], red, green, blue);
+ }
+
+ for(int y = iy[n] + 1; y <= iy[m]; y++) {
+ protected_push_tag(1 + ix[n] + ((ix[m] - ix[n]) * (y - iy[n]))/(iy[m] - iy[n]), y,
+ red, green, blue);
+ }
+
+ direction = 1;
+
+ } else if(iy[m] < iy[n]) { // LEFT BORDERS
+
+ if(direction >= 0) {
+ protected_push_tag(ix[n], iy[n], red, green, blue);
+ }
+
+ for(int y = iy[n] - 1; y >= iy[m]; y--) {
+ protected_push_tag(ix[n] + ((ix[m] - ix[n]) * (y - iy[n]))/(iy[m] - iy[n]), y,
+ red, green, blue);
+ }
+
+ direction = -1;
+
+ } else {
+
+ if(direction >= 0) {
+ protected_push_tag(ix[n]+1, iy[n], red, green, blue);
+ }
+
+ protected_push_tag(ix[m], iy[m], red, green, blue);
+
+ direction = 0;
+ }
+ }
+ }
+
+ _current_polygon++;
+}
+
+void Plotter::fill() {
+ bool in[_current_polygon];
+ for(int p = 0; p < _current_polygon; p++) in[p] = false;
+
+ scalar_t red[_current_polygon], green[_current_polygon], blue[_current_polygon];
+ Tag **u = _tag_map;
+
+ int lk = 0, k = 0;
+
+ for(int x = 0; x < _width+1; x++) {
+ _red_imap[k] = 0;
+ _green_imap[k] = 0;
+ _blue_imap[k] = 0;
+ k++;
+ }
+
+ int current_index = -1;
+ for(int y = 0; y < _height; y++) {
+ scalar_t sred = 0, sgreen = 0, sblue = 0;
+ _red_imap[k] = 0;
+ _green_imap[k] = 0;
+ _blue_imap[k] = 0;
+ k++; lk++;
+
+ for(int x = 0; x < _width; x++) {
+ for(Tag *t = *u; t; t = t->next) {
+ if(in[t->index]) {
+ in[t->index] = false;
+ if(t->index == current_index) {
+ current_index--;
+ while(current_index >= 0 && !in[current_index]) current_index--;
+ }
+ } else {
+ in[t->index] = true;
+ red[t->index] = t->red;
+ green[t->index] = t->green;
+ blue[t->index] = t->blue;
+ if(t->index > current_index) current_index = t->index;
+ }
+ }
+
+ if(current_index >= 0) {
+ sred += red[current_index];
+ sgreen += green[current_index];
+ sblue += blue[current_index];
+ }
+
+ _red_imap[k] = sred + _red_imap[lk];
+ _green_imap[k] = sgreen + _green_imap[lk];
+ _blue_imap[k] = sblue + _blue_imap[lk];
+
+ k++; lk++;
+ u++;
+ }
+ }
+}
+
+void Plotter::save_as_ppm(Universe *universe, const char *filename) {
+ reset();
+ for(int p = 0; p < universe->_nb_polygons; p++) {
+ if(universe->_polygons[p]) {
+ draw_polygon(universe->_polygons[p]);
+ }
+ }
+ fill();
+
+ unsigned char *image = new unsigned char[_width * _height * 3];
+
+ int n = 0;
+ for(int y = 0; y < _height / _scaling; y++) {
+ for(int x = 0; x < _width / _scaling; x++) {
+ image[n++] = red_sum(x * _scaling, y * _scaling, (x + 1) * _scaling, (y + 1) * _scaling) / scalar_t(_scaling * _scaling);
+ image[n++] = green_sum(x * _scaling, y * _scaling, (x + 1) * _scaling, (y + 1) * _scaling) / scalar_t(_scaling * _scaling);
+ image[n++] = blue_sum(x * _scaling, y * _scaling, (x + 1) * _scaling, (y + 1) * _scaling) / scalar_t(_scaling * _scaling);
+ }
+ }
+
+ ofstream out(filename);
+ out << "P6" << endl;
+ out << _width << " " << _height << endl;
+ out << 255 << endl;
+ out.write((char *) image, _width * _height * 3);
+ out.flush();
+
+ delete[] image;
+}
--- /dev/null
+
+// Written and (C) by Francois Fleuret
+// Contact <francois.fleuret@idiap.ch> for comments & bug reports
+
+#ifndef PLOTTER_H
+#define PLOTTER_H
+
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+
+#include "misc.h"
+#include "universe.h"
+
+class Plotter {
+ int _width, _height;
+
+ class Tag {
+ public:
+ int index;
+ scalar_t red, green, blue;
+ Tag *next;
+ };
+
+ Tag **_tag_map;
+
+ // We have our own stack of tags to avoid numerous news and deletes
+ Tag *_tag_stack, *_tag_stack_top;
+ scalar_t *_red_imap, *_green_imap, *_blue_imap;
+ int _current_polygon;
+ int _scaling;
+
+ inline void protected_push_tag(int x, int y, scalar_t r, scalar_t g, scalar_t b) {
+ if(y >= 0 && y < _height) {
+
+ if(x < 0) { x = 0; }
+ else if(x >= _width) { x = _width - 1; }
+
+ int t = y * _width + x;
+
+ _tag_stack_top->next = _tag_map[t];
+ _tag_stack_top->index = _current_polygon;
+ _tag_stack_top->red = r;
+ _tag_stack_top->green = g;
+ _tag_stack_top->blue = b;
+ _tag_map[t] = _tag_stack_top;
+ _tag_stack_top++;
+ }
+ }
+
+ inline void push_tag(int x, int y, scalar_t r, scalar_t g, scalar_t b) {
+ int t = y * _width + x;
+ _tag_stack_top->next = _tag_map[t];
+ _tag_stack_top->index = _current_polygon;
+ _tag_stack_top->red = r;
+ _tag_stack_top->green = g;
+ _tag_stack_top->blue = b;
+ _tag_map[t] = _tag_stack_top;
+ _tag_stack_top++;
+ }
+
+ inline scalar_t red_sum(int xmin, int ymin, int xmax, int ymax) {
+ return _red_imap[xmax + (_width + 1) * ymax]
+ + _red_imap[xmin + (_width + 1) * ymin]
+ - _red_imap[xmax + (_width + 1) * ymin]
+ - _red_imap[xmin + (_width + 1) * ymax];
+ }
+
+ inline scalar_t green_sum(int xmin, int ymin, int xmax, int ymax) {
+ return _green_imap[xmax + (_width + 1) * ymax]
+ + _green_imap[xmin + (_width + 1) * ymin]
+ - _green_imap[xmax + (_width + 1) * ymin]
+ - _green_imap[xmin + (_width + 1) * ymax];
+ }
+
+ inline scalar_t blue_sum(int xmin, int ymin, int xmax, int ymax) {
+ return _blue_imap[xmax + (_width + 1) * ymax]
+ + _blue_imap[xmin + (_width + 1) * ymin]
+ - _blue_imap[xmax + (_width + 1) * ymin]
+ - _blue_imap[xmin + (_width + 1) * ymax];
+ }
+
+ void reset();
+
+ void draw_polygon(Polygon *p);
+ void fill();
+public:
+
+ Plotter(int width, int height, int scaling);
+ ~Plotter();
+
+ void save_as_ppm(Universe *universe, const char *filename);
+};
+
+#endif
}
#endif
-#ifdef CAIRO_SUPPORT
-void Polygon::draw(cairo_t* context_resource) {
- cairo_set_line_width(context_resource, 1.0);
- cairo_set_source_rgb (context_resource, _red, _green, _blue);
- cairo_move_to(context_resource, _x[0], _y[0]);
- for(int n = 0; n < _nb_vertices; n++) {
- cairo_line_to(context_resource, _x[n], _y[n]);
- }
- cairo_close_path(context_resource);
- cairo_stroke_preserve(context_resource);
- cairo_fill(context_resource);
+void Polygon::draw(Canvas *canvas) {
+ canvas->set_drawing_color(_red, _green, _blue);
+ canvas->draw_polygon(1, _nb_vertices, _x, _y);
}
-void Polygon::draw_contours(cairo_t* context_resource) {
- cairo_set_line_width(context_resource, 1.0);
- cairo_set_source_rgb (context_resource, 0.0, 0.0, 0.0);
- // cairo_set_source_rgb (context_resource, 1.0, 1.0, 1.0);
- cairo_move_to(context_resource, _x[0], _y[0]);
- for(int n = 0; n < _nb_vertices; n++) {
- cairo_line_to(context_resource, _x[n], _y[n]);
- }
- cairo_close_path(context_resource);
- cairo_stroke(context_resource);
+void Polygon::draw_contours(Canvas *canvas) {
+ canvas->set_drawing_color(0.0, 0.0, 0.0);
+ canvas->draw_polygon(0, _nb_vertices, _x, _y);
}
-#endif
void Polygon::set_vertex(int k, scalar_t x, scalar_t y) {
_relative_x[k] = x;
_nb_polygons = nb_polygons;
- a = _relative_x[_nb_vertices - 1] * _relative_y[0] - _relative_x[0] * _relative_y[_nb_vertices - 1];
+ a = _relative_x[_nb_vertices - 1] * _relative_y[0]
+ - _relative_x[0] * _relative_y[_nb_vertices - 1];
+
for(int n = 0; n < _nb_vertices - 1; n++)
a += _relative_x[n] * _relative_y[n+1] - _relative_x[n+1] * _relative_y[n];
a *= 0.5;
#define POLYGON_H
#include "misc.h"
+#include "canvas.h"
+
#include "xfig_tracer.h"
#ifdef X11_SUPPORT
#include "simple_window.h"
#endif
-#ifdef CAIRO_SUPPORT
-#include <cairo.h>
-#endif
-
class Polygon {
struct Triangle {
int a, b, c;
void draw_contours(SimpleWindow *window);
#endif
-#ifdef CAIRO_SUPPORT
- void draw(cairo_t* context_resource);
- void draw_contours(cairo_t* context_resource);
-#endif
+ void draw(Canvas *canvas);
+ void draw_contours(Canvas *canvas);
void set_vertex(int k, scalar_t x, scalar_t y);
void set_position(scalar_t center_x, scalar_t center_y, scalar_t theta);
#include "universe.h"
Universe::Universe(int nb_max_polygons,
- scalar_t width, scalar_t height) : _width(width), _height(height),
- _nb_max_polygons(nb_max_polygons), _nb_polygons(0) {
+ scalar_t width, scalar_t height) : _width(width),
+ _height(height),
+ _nb_max_polygons(nb_max_polygons),
+ _nb_polygons(0) {
_polygons = new Polygon *[_nb_max_polygons];
for(int n = 0; n < _nb_max_polygons; n++) _polygons[n] = 0;
}
}
#endif
-#ifdef CAIRO_SUPPORT
-void Universe::draw(cairo_t *context_resource) {
+void Universe::draw(Canvas *canvas) {
for(int n = 0; n < _nb_polygons; n++) {
if(_polygons[n]) {
- _polygons[n]->draw(context_resource);
+ _polygons[n]->draw(canvas);
}
}
for(int n = 0; n < _nb_polygons; n++) {
if(_polygons[n]) {
- _polygons[n]->draw_contours(context_resource);
+ _polygons[n]->draw_contours(canvas);
}
}
}
-#endif
void Universe::apply_collision_forces(scalar_t dt) {
const int nb_axis = 2;
#include <cmath>
#include "misc.h"
+#include "canvas.h"
#include "polygon.h"
#ifdef X11_SUPPORT
#include "simple_window.h"
#endif
-#ifdef CAIRO_SUPPORT
-#include <cairo.h>
-#endif
-
using namespace std;
class Universe {
void draw(SimpleWindow *window);
#endif
-#ifdef CAIRO_SUPPORT
- void draw(cairo_t *context_resource);
-#endif
+ void draw(Canvas *canvas);
};
#endif