From fe0be986e63c5dabed472d68b0aa7c91ca0651db Mon Sep 17 00:00:00 2001 From: Francois Fleuret Date: Sat, 27 Aug 2016 21:42:02 +0200 Subject: [PATCH] Cosmetics + started to add support for cairo drawing to eventually replace the X window backend. --- Makefile | 6 ++- main.cc | 135 ++++++++++++++++++++++++++++++++++++------------- manipulator.cc | 2 +- polygon.cc | 19 ++++++- polygon.h | 10 ++++ retina.cc | 2 +- universe.cc | 29 ++++++++++- universe.h | 13 +++++ 8 files changed, 175 insertions(+), 41 deletions(-) diff --git a/Makefile b/Makefile index 3a41714..6fc991d 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,10 @@ endif LDFLAGS = -L/usr/X11R6/lib/ -lz -ldl +# Do we use cairo? +CXXFLAGS += -I/usr/include/cairo -DCAIRO_SUPPORT +LDFLAGS += -lcairo + TASK_SRC = dummy.cc move_square.cc hit_shape.cc TASK_OBJ = $(TASK_SRC:.cc=.task) @@ -53,6 +57,6 @@ Makefile.depend: *.h *.cc Makefile $(CC) -M *.cc > Makefile.depend clean: - \rm main *.o *.task Makefile.depend + \rm -f main *.o *.task Makefile.depend -include Makefile.depend diff --git a/main.cc b/main.cc index 9871ce0..905706d 100644 --- a/main.cc +++ b/main.cc @@ -22,6 +22,42 @@ using namespace std; #include "intelligence.h" #include "xfig_tracer.h" +#ifdef CAIRO_SUPPORT +#include + + +void generate_png(int width, int height, Universe *universe, const char *image_name) { + const int depth = 4; + 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_set_source_rgb(context_resource, 1.0, 1.0, 1.0); + cairo_rectangle(context_resource, 0, 0, width, height); + cairo_fill(context_resource); + + universe->draw(context_resource); + + cairo_surface_write_to_png(image, image_name); + + // fprintf(stdout, "Content-type: image/png\n\n"); + // cairo_surface_write_to_png_stream(image, write_cairo_to_file, stdout); + + cairo_destroy(context_resource); + cairo_surface_destroy(image); + delete[] data; +} +#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 @@ -142,7 +178,6 @@ int main(int argc, char **argv) { } cout << "FlatLand, a toy universe for goal-planning experiments." << endl; - cout << "$Id: main.cc,v 1.89 2007-06-16 13:51:53 fleuret Exp $" << endl; if(!task) { task = load_task("dummy.task"); @@ -171,7 +206,7 @@ int main(int argc, char **argv) { SimpleWindow *window_main = 0, *window_brain = 0; - int winfd = -1; + int window_main_fd = -1; MapConcatener sensory_map(2); sensory_map.add_map(&retina); @@ -197,18 +232,18 @@ int main(int argc, char **argv) { cout << "done." << endl ; } - if(!no_window) { + if(no_window) { + cout << "Started without windows." << endl; + } else { window_main = new SimpleWindow("Universe (main window)", 4, 4, task->width(), task->height()); - winfd = window_main->file_descriptor(); + window_main_fd = window_main->file_descriptor(); window_main->map(); cout << "When the main window has the focus, press `q' to quit and click and drag to move" << endl << "objects." << endl; window_brain = new SimpleWindow("Universe (brain)", - 12 + task->width(), 4, - retina.width(), retina.height() + manipulator.parameter_height()); + 12 + task->width(), 4, + retina.width(), retina.height() + manipulator.parameter_height()); window_brain->map(); - } else { - cout << "Started without windows." << endl; } int tick = 0; @@ -228,10 +263,10 @@ int main(int argc, char **argv) { if(window_main) { struct timeval tv; FD_ZERO (&fds); - FD_SET (winfd, &fds); + FD_SET (window_main_fd, &fds); tv.tv_sec = 0; tv.tv_usec = 5000; // 0.05s - r = select(winfd + 1, &fds, 0, 0, &tv); + r = select(window_main_fd + 1, &fds, 0, 0, &tv); } else r = 0; time_t t = time(0); @@ -285,10 +320,13 @@ int main(int argc, char **argv) { last_hand_x = manipulator.hand_x(); last_hand_y = manipulator.hand_y(); last_grabbing = manipulator.grabbing(); - retina.set_location(manipulator.hand_x(), manipulator.hand_y()); + + retina.set_location(manipulator.hand_x(), + manipulator.hand_y()); if(window_main) { - window_main->color(0.0, 0.0, 0.0); + // window_main->color(0.0, 0.0, 0.0); + window_main->color(1.0, 1.0, 1.0); window_main->fill(); task->draw(window_main); universe.draw(window_main); @@ -318,7 +356,7 @@ int main(int argc, char **argv) { got_event = true; - if(FD_ISSET(winfd, &fds)) { + if(FD_ISSET(window_main_fd, &fds)) { SimpleEvent se; @@ -371,18 +409,17 @@ int main(int argc, char **argv) { case SimpleEvent::MOUSE_MOTION: { - if(press_shift) manipulator.force_move(se.x, se.y); - else { - if(grabbed_polygon) { - scalar_t xf, yf, force_x, force_y, f, fmax = 100; - xf = grabbed_polygon->absolute_x(relative_grab_x, relative_grab_y); - yf = grabbed_polygon->absolute_y(relative_grab_x, relative_grab_y); - force_x = se.x - xf; - force_y = se.y - yf; - f = sqrt(sq(force_x) + sq(force_y)); - if(f > fmax) { force_x = (force_x * fmax)/f; force_y = (force_y * fmax)/f; } - grabbed_polygon->apply_force(0.1, xf, yf, force_x, force_y); - } + if(press_shift) { + manipulator.force_move(se.x, se.y); + } else if(grabbed_polygon) { + scalar_t xf, yf, force_x, force_y, f, fmax = 100; + xf = grabbed_polygon->absolute_x(relative_grab_x, relative_grab_y); + yf = grabbed_polygon->absolute_y(relative_grab_x, relative_grab_y); + force_x = se.x - xf; + force_y = se.y - yf; + f = sqrt(sq(force_x) + sq(force_y)); + if(f > fmax) { force_x = (force_x * fmax)/f; force_y = (force_y * fmax)/f; } + grabbed_polygon->apply_force(0.1, xf, yf, force_x, force_y); } break; } @@ -390,23 +427,53 @@ int main(int argc, char **argv) { case SimpleEvent::KEY_PRESS: { - if(strcmp(se.key, "q") == 0) quit = true; + if(strcmp(se.key, "q") == 0) { + quit = true; + } + else if(strcmp(se.key, "s") == 0) { + retina.save_as_ppm("/tmp/retina.ppm"); + cout << "Retina screen shot saved in /tmp/retina.ppm" << endl; { XFigTracer tracer("/tmp/universe.fig"); universe.print_xfig(&tracer); } + +#ifdef CAIRO_SUPPORT + generate_png(task->width(), task->height(), &universe, "/tmp/universe.png"); +#endif + + } + + else if(strcmp(se.key, "Shift_L") == 0 || strcmp(se.key, "Shift_R") == 0) { + press_shift = true; + } + + else if(strcmp(se.key, "Up") == 0) { + manipulator.do_action(Manipulator::ACTION_MOVE_UP); + } + + else if(strcmp(se.key, "Right") == 0) { + manipulator.do_action(Manipulator::ACTION_MOVE_RIGHT); + } + + else if(strcmp(se.key, "Down") == 0) { + manipulator.do_action(Manipulator::ACTION_MOVE_DOWN); + } + + else if(strcmp(se.key, "Left") == 0) { + manipulator.do_action(Manipulator::ACTION_MOVE_LEFT); + } + + else if(strcmp(se.key, "g") == 0) { + manipulator.do_action(Manipulator::ACTION_GRAB); + } + + else if(strcmp(se.key, "r") == 0) { + manipulator.do_action(Manipulator::ACTION_RELEASE); } - else if(strcmp(se.key, "Shift_L") == 0 || strcmp(se.key, "Shift_R") == 0) press_shift = true; - - else if(strcmp(se.key, "Up") == 0) manipulator.do_action(Manipulator::ACTION_MOVE_UP); - else if(strcmp(se.key, "Right") == 0) manipulator.do_action(Manipulator::ACTION_MOVE_RIGHT); - else if(strcmp(se.key, "Down") == 0) manipulator.do_action(Manipulator::ACTION_MOVE_DOWN); - else if(strcmp(se.key, "Left") == 0) manipulator.do_action(Manipulator::ACTION_MOVE_LEFT); - else if(strcmp(se.key, "g") == 0) manipulator.do_action(Manipulator::ACTION_GRAB); - else if(strcmp(se.key, "r") == 0) manipulator.do_action(Manipulator::ACTION_RELEASE); else if(strcmp(se.key, "space") == 0) { switch(action_mode) { diff --git a/manipulator.cc b/manipulator.cc index d42dfb7..7455d5b 100644 --- a/manipulator.cc +++ b/manipulator.cc @@ -247,7 +247,7 @@ void Manipulator::draw_on_universe(SimpleWindow *window) { int xc = int(_hand_x), yc = int(_hand_y); const int delta = 5; - window->color(1.0, 1.0, 1.0); + window->color(0.25, 0.25, 0.25); window->draw_line(xc - delta, yc, xc + delta, yc); window->draw_line(xc, yc - delta, xc, yc + delta); diff --git a/polygon.cc b/polygon.cc index 2ae238d..e957ec1 100644 --- a/polygon.cc +++ b/polygon.cc @@ -73,10 +73,26 @@ void Polygon::draw_contours(SimpleWindow *window) { y[n] = int(_y[n]); } window->color(0.0, 0.0, 0.0); - for(int n = 0; n < _nb_vertices; n++) + for(int n = 0; n < _nb_vertices; n++) { window->draw_line(x[n], y[n], x[(n+1)%_nb_vertices], y[(n+1)%_nb_vertices]); + } } +#ifdef CAIRO_SUPPORT +void Polygon::draw(cairo_t* context_resource) { +} + +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); + for(int n = 0; n < _nb_vertices; n++) { + cairo_move_to(context_resource, _x[n], _y[n]); + cairo_line_to(context_resource, _x[(n+1)%_nb_vertices], _y[(n+1)%_nb_vertices]); + } + cairo_stroke(context_resource); +} +#endif + void Polygon::set_vertex(int k, scalar_t x, scalar_t y) { _relative_x[k] = x; _relative_y[k] = y; @@ -489,4 +505,3 @@ bool Polygon::collide(Polygon *p) { return false; } - diff --git a/polygon.h b/polygon.h index add154b..46eda3e 100644 --- a/polygon.h +++ b/polygon.h @@ -9,6 +9,10 @@ #include "simple_window.h" #include "xfig_tracer.h" +#ifdef CAIRO_SUPPORT +#include +#endif + class Polygon { struct Triangle { int a, b, c; @@ -71,6 +75,12 @@ public: void draw(SimpleWindow *window); void draw_contours(SimpleWindow *window); + +#ifdef CAIRO_SUPPORT + void draw(cairo_t* context_resource); + void draw_contours(cairo_t* context_resource); +#endif + 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); void set_speed(scalar_t dcenter_x, scalar_t dcenter_y, scalar_t dtheta); diff --git a/retina.cc b/retina.cc index db0f543..4e591b1 100644 --- a/retina.cc +++ b/retina.cc @@ -271,7 +271,7 @@ void Retina::update_map() { } void Retina::draw_on_universe(SimpleWindow *window) { - window->color(1.0, 1.0, 1.0); + window->color(0.25, 0.25, 0.25); int xc = int(_eye_x), yc = int(_eye_y); window->draw_line(xc - _width/2, yc - _height/2, xc + _width/2, yc - _height/2); window->draw_line(xc + _width/2, yc - _height/2, xc + _width/2, yc + _height/2); diff --git a/universe.cc b/universe.cc index 48d8efc..9522dfd 100644 --- a/universe.cc +++ b/universe.cc @@ -130,9 +130,34 @@ void Universe::print_xfig(XFigTracer *tracer) { } void Universe::draw(SimpleWindow *window) { - for(int n = 0; n < _nb_polygons; n++) if(_polygons[n]) _polygons[n]->draw(window); - for(int n = 0; n < _nb_polygons; n++) if(_polygons[n]) _polygons[n]->draw_contours(window); + for(int n = 0; n < _nb_polygons; n++) { + if(_polygons[n]) { + _polygons[n]->draw(window); + } + } + + for(int n = 0; n < _nb_polygons; n++) { + if(_polygons[n]) { + _polygons[n]->draw_contours(window); + } + } +} + +#ifdef CAIRO_SUPPORT +void Universe::draw(cairo_t *context_resource) { + for(int n = 0; n < _nb_polygons; n++) { + if(_polygons[n]) { + _polygons[n]->draw(context_resource); + } + } + + for(int n = 0; n < _nb_polygons; n++) { + if(_polygons[n]) { + _polygons[n]->draw_contours(context_resource); + } + } } +#endif void Universe::apply_collision_forces(scalar_t dt) { const int nb_axis = 2; diff --git a/universe.h b/universe.h index 74339a3..3bbbf4a 100644 --- a/universe.h +++ b/universe.h @@ -8,6 +8,10 @@ #include #include +#ifdef CAIRO_SUPPORT +#include +#endif + using namespace std; #include "misc.h" @@ -19,21 +23,30 @@ class Universe { public: int _nb_max_polygons, _nb_polygons; Polygon **_polygons; + Universe(int nb_max_polygons, scalar_t xmax, scalar_t ymax); // The destructor deletes all the added polygons ~Universe(); + void initialize(Polygon *p); void clear(); void add_polygon(Polygon *p); bool collide(Polygon *p); + // Compute collisions between projections of the polygons on a few // axis to speed up the computation void compute_pseudo_collisions(int nb_axis, int *nb_colliding_axis); void apply_collision_forces(scalar_t dt); bool update(scalar_t dt); + Polygon *pick_polygon(scalar_t x, scalar_t y); + void print_xfig(XFigTracer *tracer); void draw(SimpleWindow *window); + +#ifdef CAIRO_SUPPORT + void draw(cairo_t *context_resource); +#endif }; #endif -- 2.20.1