Cosmetics + started to add support for cairo drawing to eventually replace the X...
authorFrancois Fleuret <francois@fleuret.org>
Sat, 27 Aug 2016 19:42:02 +0000 (21:42 +0200)
committerFrancois Fleuret <francois@fleuret.org>
Sat, 27 Aug 2016 19:42:02 +0000 (21:42 +0200)
Makefile
main.cc
manipulator.cc
polygon.cc
polygon.h
retina.cc
universe.cc
universe.h

index 3a41714..6fc991d 100644 (file)
--- 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 (file)
--- a/main.cc
+++ b/main.cc
@@ -22,6 +22,42 @@ using namespace std;
 #include "intelligence.h"
 #include "xfig_tracer.h"
 
+#ifdef CAIRO_SUPPORT
+#include <cairo.h>
+
+
+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) {
index d42dfb7..7455d5b 100644 (file)
@@ -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);
index 2ae238d..e957ec1 100644 (file)
@@ -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;
 }
-
index add154b..46eda3e 100644 (file)
--- a/polygon.h
+++ b/polygon.h
@@ -9,6 +9,10 @@
 #include "simple_window.h"
 #include "xfig_tracer.h"
 
+#ifdef CAIRO_SUPPORT
+#include <cairo.h>
+#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);
index db0f543..4e591b1 100644 (file)
--- 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);
index 48d8efc..9522dfd 100644 (file)
@@ -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;
index 74339a3..3bbbf4a 100644 (file)
@@ -8,6 +8,10 @@
 #include <iostream>
 #include <cmath>
 
+#ifdef CAIRO_SUPPORT
+#include <cairo.h>
+#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