utils/mobility-visualizer-view.cc
changeset 5093 2dc19210c693
parent 5092 39e4d3a81e1c
parent 4559 51fb48b38c2f
child 5094 b98a7a92f020
equal deleted inserted replaced
5092:39e4d3a81e1c 5093:2dc19210c693
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
       
     2 
       
     3 #include <map>
       
     4 
       
     5 #include <goocanvas.h>
       
     6 #include <glib/gthread.h>
       
     7 
       
     8 #include "mobility-visualizer.h"
       
     9 #include <map>
       
    10 #include "ns3/simulator.h"
       
    11 
       
    12 #define MAX_QUEUE_LENGTH 100
       
    13 #define MAX_EVENTS 20
       
    14 #define LOOKAHEAD_SECONDS 10
       
    15 
       
    16 GtkWidget *g_canvas;
       
    17 
       
    18 int model_init (int argc, char *argv[]);
       
    19 
       
    20 struct Node
       
    21 {
       
    22   GooCanvasItem *m_item;
       
    23   GooCanvasItem *m_vector;
       
    24   void create ()
       
    25   {
       
    26     GooCanvasItem *root = goo_canvas_get_root_item (GOO_CANVAS (g_canvas));
       
    27     m_item = goo_canvas_ellipse_new (root, 0, 0, 2.0, 2.0,
       
    28                                      "line_width", 0.5,
       
    29                                      "stroke_color", "black",
       
    30                                      "fill_color", "red",
       
    31                                      NULL);
       
    32 
       
    33     m_vector = goo_canvas_polyline_new (root, FALSE, 0,
       
    34                                         "line_width", 0.3,
       
    35                                         "stroke_color", "black",
       
    36                                         "end-arrow", TRUE,
       
    37                                         "arrow-length", 10.0,
       
    38                                         "arrow-width", 10.0,
       
    39                                         NULL);
       
    40     
       
    41   }
       
    42 
       
    43 
       
    44   void update (double x, double y, double vx, double vy)
       
    45   {
       
    46     g_object_set (m_item, "center_x", x, "center_y", y, NULL);
       
    47     
       
    48     if (vx == 0 && vy == 0)
       
    49       {
       
    50         GooCanvasPoints *points = goo_canvas_points_new (0);
       
    51         g_object_set (m_vector, "points", points, NULL);
       
    52         goo_canvas_points_unref (points);
       
    53       }
       
    54     else
       
    55       {
       
    56         GooCanvasPoints *points = goo_canvas_points_new (2);
       
    57 
       
    58         points->coords[0] = x;
       
    59         points->coords[1] = y;
       
    60         points->coords[2] = x + vx;
       
    61         points->coords[3] = y + vy;
       
    62 
       
    63         g_object_set (m_vector, "points", points, NULL);
       
    64         goo_canvas_points_unref (points);
       
    65       }
       
    66   }
       
    67 };
       
    68 
       
    69 std::map<void*, Node> g_nodes;
       
    70 
       
    71 GTimeVal initialTime = {-1, -1};
       
    72 gboolean firstTime = TRUE;
       
    73 double g_lookaheadTime = 0;
       
    74 GStaticMutex g_lookaheadTimeMux = G_STATIC_MUTEX_INIT;
       
    75 ViewUpdateData *g_nextData = NULL;
       
    76 
       
    77 
       
    78 GAsyncQueue *queue;
       
    79 
       
    80 #define TIME_SCALE 1
       
    81 
       
    82 double get_current_time ()
       
    83 {
       
    84   GTimeVal currTime;
       
    85   g_get_current_time (&currTime);
       
    86   GTimeVal relativeTime;
       
    87   relativeTime.tv_sec = currTime.tv_sec - initialTime.tv_sec + LOOKAHEAD_SECONDS;
       
    88   relativeTime.tv_usec = currTime.tv_usec;
       
    89   g_time_val_add (&relativeTime, -initialTime.tv_usec);
       
    90   return (relativeTime.tv_sec + 1.0e-6*relativeTime.tv_usec)*TIME_SCALE;
       
    91 }
       
    92 
       
    93 // called from the simulation thread
       
    94 void view_update (ViewUpdateData *updateData)
       
    95 {
       
    96   while ((g_static_mutex_lock (&g_lookaheadTimeMux), g_lookaheadTime) != 0 and updateData->time >= g_lookaheadTime)
       
    97     {
       
    98       g_static_mutex_unlock (&g_lookaheadTimeMux);
       
    99       g_usleep ((gulong) 10e3);
       
   100     }
       
   101   g_static_mutex_unlock (&g_lookaheadTimeMux);
       
   102   g_async_queue_push (queue, updateData);
       
   103 }
       
   104 
       
   105 void view_update_process (ViewUpdateData *updateData)
       
   106 {
       
   107   for (std::vector<NodeUpdate>::const_iterator update
       
   108          = updateData->updateList.begin ();
       
   109        update != updateData->updateList.end ();
       
   110        update++)
       
   111     {
       
   112       if (g_nodes.find (update->node) == g_nodes.end ())
       
   113         {
       
   114           g_nodes[update->node].create ();
       
   115         }
       
   116       g_nodes[update->node].update (update->x, update->y, update->vx, update->vy);
       
   117     }
       
   118   delete updateData;
       
   119 }
       
   120 
       
   121 gboolean view_update_consumer ()
       
   122 {
       
   123   if (firstTime)
       
   124     {
       
   125       firstTime = FALSE;
       
   126       g_get_current_time (&initialTime);
       
   127     }
       
   128 
       
   129   double now = get_current_time ();
       
   130   g_static_mutex_lock (&g_lookaheadTimeMux);
       
   131   g_lookaheadTime = now + LOOKAHEAD_SECONDS;
       
   132   g_static_mutex_unlock (&g_lookaheadTimeMux);
       
   133 
       
   134   if (!g_nextData)
       
   135     g_nextData = (ViewUpdateData *) g_async_queue_try_pop (queue);
       
   136 
       
   137   if (!g_nextData)
       
   138     return TRUE;
       
   139   
       
   140   if (g_nextData->time > now)
       
   141     return TRUE;
       
   142 
       
   143   do
       
   144     {
       
   145       view_update_process (g_nextData);
       
   146       g_nextData = (ViewUpdateData *) g_async_queue_try_pop (queue);
       
   147     }
       
   148   while (g_nextData && g_nextData->time <= now);
       
   149 
       
   150   return TRUE;
       
   151 }
       
   152 
       
   153 void zoom_changed (GtkAdjustment *adj)
       
   154 {
       
   155   goo_canvas_set_scale (GOO_CANVAS (g_canvas), gtk_adjustment_get_value (adj));
       
   156 }
       
   157 
       
   158 int main (int argc, char *argv[])
       
   159 {
       
   160   g_thread_init (NULL);
       
   161   gtk_init (&argc, &argv);
       
   162   double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
       
   163 
       
   164   model_init (argc, argv, &x1, &y1, &x2, &y2);
       
   165 
       
   166   GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
       
   167   gtk_window_set_default_size (GTK_WINDOW (window), 640, 600);
       
   168   gtk_widget_show (window);
       
   169   g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
       
   170 
       
   171   GtkWidget *scrolled_win = gtk_scrolled_window_new (NULL, NULL);
       
   172   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
       
   173   gtk_widget_show (scrolled_win);
       
   174 
       
   175   GtkWidget *vbox = gtk_vbox_new (FALSE, 4);
       
   176   gtk_widget_show (vbox);
       
   177   gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, 1, 1, 4);
       
   178   gtk_container_add (GTK_CONTAINER (window), vbox);
       
   179 
       
   180   GtkWidget *hbox = gtk_hbox_new (FALSE, 4);
       
   181   gtk_widget_show (hbox);
       
   182   gtk_box_pack_start (GTK_BOX (vbox), hbox, false, false, 4);
       
   183 
       
   184   GtkObject *zoom = gtk_adjustment_new (3.0, 0.1, 10.0, 0.2, 1.0, 1.0);
       
   185   gtk_box_pack_start(GTK_BOX (hbox),
       
   186                      GTK_WIDGET (g_object_new (GTK_TYPE_SPIN_BUTTON, "adjustment", zoom,
       
   187                                                "visible", true, "digits", 2, NULL)),
       
   188                      false, false, 4);
       
   189 
       
   190   g_canvas = goo_canvas_new ();
       
   191   gtk_widget_set_size_request (GTK_WIDGET (g_canvas), 600, 450);
       
   192   goo_canvas_set_bounds (GOO_CANVAS (g_canvas), -500, -500, 500, 500);
       
   193   g_signal_connect (zoom, "value-changed", G_CALLBACK (zoom_changed), NULL);
       
   194   gtk_adjustment_value_changed (GTK_ADJUSTMENT (zoom));
       
   195   gtk_widget_show (g_canvas);
       
   196   gtk_container_add (GTK_CONTAINER (scrolled_win), g_canvas);
       
   197 
       
   198   goo_canvas_scroll_to (GOO_CANVAS (g_canvas), 0, 0);
       
   199 
       
   200   // create the bounds rectangle
       
   201   if (x1 != x2)
       
   202     {
       
   203       GooCanvasItem *item = 
       
   204         goo_canvas_rect_new (goo_canvas_get_root_item (GOO_CANVAS (g_canvas)),
       
   205                                                  x1, y1, x2-x1, y2-y1, NULL);
       
   206         g_object_set (item, "line-width", 1.0, "stroke-color", "grey", NULL);
       
   207     }
       
   208 
       
   209   queue = g_async_queue_new ();
       
   210 
       
   211   g_timeout_add ((guint) (SAMPLE_INTERVAL*1000), (GSourceFunc) view_update_consumer, NULL);
       
   212 
       
   213   g_thread_create (GThreadFunc (ns3::Simulator::Run), NULL, FALSE, NULL);
       
   214 
       
   215   gtk_main ();
       
   216 
       
   217   return 0;
       
   218 }