Board index FlightGear Development Canvas

Using Canvas for visualizing orbital flights (cont'd PM)

Canvas is FlightGear's new fully scriptable 2D drawing system that will allow you to easily create new instruments, HUDs and even GUI dialogs and custom GUI widgets, without having to write C++ code and without having to rebuild FlightGear.

Re: Using Canvas for visualizing orbital flights (cont'd PM)

Postby Hooray » Thu Apr 16, 2015 7:36 am

right, sorry for not being clear about it: I was referring to the reusing previously created point objects (as in the property tree), by merely changing their x/y positions - and simply hiding those not needed (using the .hide() method) - which means that you'd basically only have the allocation overhead once (i.e. during initialization).
The other obvious optimization is using a cubic/qudratic curve instead of hundreds of line segments (as I mentioned previously).

Basically, the idea is to have as little property I/O as possible - in terms of total property updates, but also total number of individual properties vs. "parametric" updates that don't create as much I/O (see the property browser to inspect how many nodes are created/removed during each update). In that sense, removeAllChildren() works analogous to delete() or free() in C/C++, whereas createChild("...") works like new/malloc - so you'd want to minimize those, and ideally use a data structure/drawing type that is appropriate (e.g. using a parametric curve instead of tons of line segments to approximate a curve)

TheTom posted these, and a few other, optimization suggestions in the original "fgplot" thread, including Nasal/Canvas code snippets.
You can use systime() and/or debug.benchmark() to see how much of a difference this makes for this particular use-case.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11836
Joined: Tue Mar 25, 2008 8:40 am

Re: Using Canvas for visualizing orbital flights (cont'd PM)

Postby Hooray » Fri Apr 17, 2015 7:14 pm

As a first step, I have edited the Canvas Snippets article to demonstrate how to draw quadratic/cubic curves (this should help lower the total number of Canvas path elements needed, because you're currently using a high number of line segments for approximating the curve):

http://wiki.flightgear.org/Canvas_Snipp ... enVG_Paths

Image

Image

Once this is working, I would consider creating an array (=Nasal vector) of path objects and simply update (translate, hide/show) those instead of using removeAllChildren() - so instead of invoking removeAllChildren(), you'd merely hide(), update()/transform() and show() the corresponding path elements

Also see:
Subject: kuifje09's FGPlot Development
TheTom wrote:Try the following version (and update fgdata). I'm not able to see any change in framerate or time with it. It creates a continuously scrolling plot by adding one segment at the end of each path per frame and removing the first segment if too much segments are present (can be changed to keep a longer history for eg. zooming and scrolling).
Code: Select all
  <load> <!-- when the fgplot is loaded ?? == pressed equipment-fgplot -->
  <![CDATA[

  # general values to have something at startup.
  var setProps = func () {
     var a = getprop("/gui/fgplot/running") or 0;
     if(a == 0) {
     setprop("/gui/fgplot/name[0]","fdm-head.rror-deg");
     setprop("/gui/fgplot/name[1]","heading-.rror-deg");
     setprop("/gui/fgplot/name[2]","true-hea.rror-deg");
     setprop("/gui/fgplot/name[3]","nav1-course-error");
     setprop("/gui/fgplot/name[4]","nav1-hea.rror-deg");
     setprop("/gui/fgplot/name[5]","nav1-tra.rror-deg");
     setprop("/gui/fgplot/prop[0]","/autopilot/internal/fdm-heading-bug-error-deg");
     setprop("/gui/fgplot/prop[1]","/autopilot/internal/heading-bug-error-deg");
     setprop("/gui/fgplot/prop[2]","/autopilot/internal/true-heading-error-deg");
     setprop("/gui/fgplot/prop[3]","/autopilot/internal/nav1-course-error");
     setprop("/gui/fgplot/prop[4]","/autopilot/internal/nav1-heading-error-deg");
     setprop("/gui/fgplot/prop[5]","/autopilot/internal/nav1-track-error-deg");
     for( var j = 0 ; 6 > j ; j += 1)
     {
       setprop("/gui/fgplot/factor["~j~"]",-1);
       setprop("/gui/fgplot/top["~j~"]",360);
       setprop("/gui/fgplot/line["~j~"]",1);
     }
     setprop("/gui/fgplot/running",0);
     setprop("/gui/fgplot/version",1);
     setprop("/gui/fgplot/plot",0);
     setprop("/gui/fgplot/transparency",0.0);
  #   gui.popupTip("Properties set",3);
     };
  };
  setProps();
 
 
   var SetTransparency = func () {
       if(getprop("/gui/fgplot/transparency")==1){
          my_canvas.setColorBackground(0,0,0,1); # Transparancy == last 0
          setprop("/gui/fgplot/transparency",0);
       } else {
          my_canvas.setColorBackground(0,0,0,0); # Transparancy == last 0
          setprop("/gui/fgplot/transparency",1);
       };
   };

  var SetLine = func(a)
  {
    setprop("/gui/fgplot/line["~a~"]", !getprop("/gui/fgplot/line["~a~"]"));
  };

  # canvas-specific code here
  var my_canvas = canvas.get( cmdarg() ); # Handle to the parent canvas
  my_canvas.set("mipmapping", 1)
           .setColorBackground(0,0,0,1); # Transparancy when last digit == 0

  var root = my_canvas.createGroup();

  var graph = root.createChild("group");

  # center of the graph.
  var x_axis =
    graph.createChild("path", "x-axis")
         .moveTo(0, 151)        # start of centerline horizontaly
         .lineTo(800, 151)      # end of centerline hor. but ends too soon
         .setColor(0.8,0.8,0.8)
         .setStrokeLineWidth(1);

  var colors = [
    "#ff0000",
    "#00ff00",
    "#0000ff",
    "#ff8000",
    "#008080",
    "#8080ff"
  ];
  var num_plots = size(colors);
  var plots = setsize([], num_plots);
  for(var i = 0; i< num_plots; i+=1)
  plots[i] = graph.createChild("path", "data")
                  .set("stroke", colors[i])
                  .set("stroke-width", 2);

  var max_x = 800;
  var dx = 2;
  var cur_x = 0;
  var x_offset = max_x;

  var doPlot = func()
  {
    var MyTimeout = func()
    {
      if( getprop("/gui/fgplot/running") != 1 )
        return;

      for(var i = 0; i < 6; i += 1)
      {
        if( getprop("/gui/fgplot/line[" ~ i ~ "]") != 1 )
          continue;

        var y = getprop(getprop("/gui/fgplot/prop[" ~ i ~ "]")) * getprop("/gui/fgplot/factor[" ~ i ~ "]");
        if( cur_x == 0 )
          plots[i].moveTo(cur_x, y);
        else
          plots[i].lineTo(cur_x, y);
        plots[i].setTranslation(x_offset, 151);

        if( plots[i].getNumSegments() > max_x / dx )
          plots[i].pop_front();
      }

      x_offset -= dx;
      cur_x += dx;

      settimer(MyTimeout,0.1);
    };

    MyTimeout();
  };
  ]]>
  </load>
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11836
Joined: Tue Mar 25, 2008 8:40 am

Previous

Return to Canvas

Who is online

Users browsing this forum: No registered users and 0 guests