Board index FlightGear Development Canvas

Cannot use .setText on SVG text element  Topic is solved

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.

Cannot use .setText on SVG text element  

Postby omega95 » Wed Jul 16, 2014 10:08 pm

I've been working on a new (airbus) vertical situation display, but I can't seem to get it to work properly.

I'm using the Basic Example in this wiki page - http://wiki.flightgear.org/Howto:Use_SVG_inside_a_Canvas#Basic_example by doing this-

But I get an error that says -
Code: Select all
Nasal runtime error: non-objects have no members
  at /home/narendran/fgfs/projects/A380/Models/Instruments/ND/vsd.nas, line 79


Where the line is -
Code: Select all
me.group.getElementById("text_range1").setText(int(me.range*0.25));


I have a feeling it's not able to get the ElementById("text_range1") but I have an objet with that name in the SVG file.

Here's the vsd hash for reference - (ofcourse, it's not complete)
Code: Select all
var vsd = {
new: func(efis_id, obj_name, switches, interface_props, svg_path) {
      var t = {parents:[vsd]};
      
      # Initialize VSD Display
      t.display = canvas.new({
         "name": "vsdScreen",
         "size": [1024, 512],
         "view": [1024, 512],
         "mipmapping": 1
      });
      
      t.efis_id = efis_id;
      t.switches = switches;
      t.interface_props = interface_props;
      
      # Add placement onto 3D model
      t.display.addPlacement({"node": obj_name});
      
      # Create canvas group
      t.group = t.display.createGroup();
      
      # Load Vertical Situation Display
      canvas.parsesvg(t.group, svg_path);

      return t;
   },
   init: func {
      me.UPDATE_INTERVAL = 0.1;
      me.loopid = 0;
      me.reset();
   },
   update: func {
      # Set Range Numbers
      me.range = getprop("/instrumentation/efis["~me.efis_id~"]"~me.switches['set_range'].path);
      me.group.getElementById("text_range1").setText(int(me.range*0.25));
      me.group.getElementById("text_range2").setText(int(me.range*0.50));
      me.group.getElementById("text_range3").setText(int(me.range*0.75));
      me.group.getElementById("text_range4").setText(int(me.range));
      
      # Set Altitude Numbers
      me.altitude = getprop(me.interface_props.altitude_ind);
      foreach(var alt; [10000, 20000, 30000, 40000]) {
         if(me.altitude <= alt) {
            me.alt_ceil = alt;
            break;
         }
      }
      me.group.getElementById("text_alt1").setText(int(me.alt_ceil/2));
      me.group.getElementById("text_alt2").setText(me.alt_ceil);
      
      # Move Aircraft Pointer
      me.group.getElementById("aircraft_marker").setTranslation(0,262*(me.altitude/me.alt_ceil));
      me.group.getElementById("speed_arrow").setTranslation(0,262*(me.altitude/me.alt_ceil));
      
      # Move Altitude Setting Line
      me.group.getElementById("altitude_set").setTranslation(0,262*(getprop("/instrumentation/efis["~me.efis_id~"]"~me.interface_props.ap_altitude_set)/me.alt_ceil));
      
   },
   reset: func {
      me.loopid += 1;
      me._loop_(me.loopid);
   },
   _loop_: func(id) {
      id = me.loopid or return;
      me.update();
      settimer(func {me._loop_(id); }, me.UPDATE_INTERVAL);
   }
};


EDIT - Btw, it seems to be loading the svg file on to the canvas file, it just doesn't let me access the objects.
Last edited by omega95 on Thu Jul 17, 2014 2:36 am, edited 1 time in total.
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Editing VSG elements on canvas

Postby omega95 » Wed Jul 16, 2014 10:24 pm

Aha, I open the svg file as an xml and found that the text was not set as a text object but a flow root - I fixed that and now I get this error -

Code: Select all
Nasal runtime error: No such member: setText
  at /home/narendran/fgfs/projects/A380/Models/Instruments/ND/vsd.nas, line 95


Same line btw, I moved some stuff around so that's what changed the line number.
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Cannot use .setText on SVG text element

Postby Hooray » Thu Jul 17, 2014 12:56 pm

the object you are accessing simply isn't a Canvas.Text node - use debug.dump() to see what you've got there, and check the console for SVG related errors.
We have a fairly simple, and incomplete, SVG parser implemented in svg.nas
Please refer to the wiki for working examples
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: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Cannot use .setText on SVG text element

Postby omega95 » Thu Jul 17, 2014 3:04 pm

simply isn't a Canvas.Text node


Thank you very much! That was it! I created the text using the text tool in inkscape but it didn't seem to work. I then copied a text element from the ND.svg texture and renamed the objects and it worked!

Also, I'm currently just using some code I found in my old 787-8 VSD but I found an ALT-profile layer in http://wiki.flightgear.org/Canvas_MapStructure_Layers. Is that supposed to do the same thing as plot the waypoint altitudes?

I still have these hashes available to make this a little more generic - the user can change the properties for things like the route manager/custom-flightplan management system, switches etc. like in the ND.
Code: Select all
# Define custom aircraft cockpit switches to be interfaced
var mySwitches = {
   'set_range':       {   path: '/inputs/range-nm'   , value: 10   },
   'toggle_waypoints':   {   path: '/inputs/wpt'         , value: 0   },
   'toggle_cstr':      {   path: '/inputs/cstr'      , value: 0   }
};

# Define interface props and functions to use the flightplan management system and aircraft instrumentation

# A380 Flightplan management system properties
var myProps_A380 = {
   curWptId:   '/flight-management/flightplan/currentWpt',
   wpt_data:    {
      # Change the return properties to suit your custom route manager system
      ident: func(n) {
         return '/flight-management/flightplan/wpt['~n~']/ident';
      },
      latitude: func(n) {
         return '/flight-management/flightplan/wpt['~n~']/latitude';
      },
      longitude: func(n) {
         return '/flight-management/flightplan/wpt['~n~']/longitude';
      },
      alt_cstr: func(n) {
         return '/flight-management/flightplan/wpt['~n~']/altitude';
      }
   },
   num_wpts:         '/flight-management/flightplan/num-wpts',
   altitude_ind:      '/instrumentation/altimeter/indicated-altitude-ft',
   heading_ind:      '/instrumentation/heading-indicator/indicated-heading-deg',
   ap_altitude_set:   '/flight-management/fcu-values/alt',
   vertSpd_ind:      '/instrumentation/vertical-speed-indicator/indicated-speed-kts'
};

# FGRouteManager and generic autopilot system properties
var myProps = {
   curWptId:   '/autopilot/route-manager/current-wp',
   wpt_data:    {
      # Change the return properties to suit your custom route manager system
      ident: func(n) {
         return '/autopilot/route-manager/route/wp['~n~']/id';
      },
      latitude: func(n) {
         return '/autopilot/route-manager/route/wp['~n~']/latitude-deg';
      },
      longitude: func(n) {
         return '/autopilot/route-manager/route/wp['~n~']/longitude-deg';
      },
      alt_cstr: func(n) {
         return '/autopilot/route-manager/route/wp['~n~']/altitude-ft';
      }
   },
   num_wpts:         '/autopilot/route-manager/route/num',
   altitude_ind:      '/instrumentation/altimeter/indicated-altitude-ft',
   heading_ind:      '/instrumentation/heading-indicator/indicated-heading-deg',
   ap_altitude_set:   '/flight-management/fcu-values/alt', # '/autopilot/settings/target-altitude-ft',
   vertSpd_ind:      '/velocities/vertical-speed-fps'
};


But I will definitely get rid of the numbers and replace them with variables after I get the basic thing done.

I've also replaced a lot of things in the VSD loop with setlisteners (like the range, cstr, wpt properties) and it seems to be a lot better. I also haven't had FG crash since and I'm getting 30+ fps. :)

Now, I just need to draw the altitude constraint lines, figure out how to draw a circle without using arcSmallCCWTo (or something similar) for the waypoints and get the elevation profile along the flight path instead of in a straight line (the last one is pretty easy).

Took care of that before submitting this reply. :D

Image

EDIT - Oh and btw, the green arrow doesn't seem to be rotating properly.
I used this -
Code: Select all
me.group.getElementById("speed_arrow").setCenter(245,294 + me.new_markerPos)
                                      .setRotation(-fpa);


But it still seems to rotate about the top left corner of the canvas screen.
294 + me.new_markerPos is the height it's at by the way.
Last edited by omega95 on Thu Jul 17, 2014 3:15 pm, edited 1 time in total.
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Cannot use .setText on SVG text element

Postby Gijs » Thu Jul 17, 2014 3:14 pm

Looks like a cool feature! :-)

ALT-profile is used to draw T/D, T/C etc. Waypoint altitude is displayed (in text) below each waypoint ID on the active route (when input to the route manager). It's visible in your screenshot. See WPT.lcontroller line 43 onwards for the altitude retrieval function.

PS: Just noticed a bug, we shouldn't display fixes when those waypoints are part of the active route. Makes no sense to display the same point twice :-)
Airports: EHAM, EHLE, KSFO
Aircraft: 747-400
User avatar
Gijs
Moderator
 
Posts: 9544
Joined: Tue Jul 03, 2007 3:55 pm
Location: Delft, the Netherlands
Callsign: PH-GYS
Version: Git
OS: Windows 10

Re: Cannot use .setText on SVG text element

Postby Hooray » Thu Jul 17, 2014 6:32 pm

Agreed, excellent job you've done there, kudos !
You have even already integrated your VSD with Gijs' ND code.
I suggest you prepare your code so that you can post it here and we can take a look - the code freeze is over now, so we can look at integrating things properly.
On the MapStructure side of things, I would prefer this to be extended to support vertical layers, and vertical "controllers/symbol" files.
Once we have native/hard-coded support for vertical projections, we can then easily replace the existing Nasal routines.


We can probably generalize some things in the WPT/RTE/ALT-profile layers to also support vertical modes, I guess Philosopher can come up with some pointers - and I can handle the implementation.

So far, your code looks good to me - but like I said, it would be better to turn it into a conventional "layer" so that it can be easily reused by other aircraft, and GUI dialogs.
That should not be much work - but we should make sure that it's sufficiently customizable, i.e. via styling and custom properties.
For instance, most aircraft won't require this VSD, while others may want to provide it optionally.
That is what the ND "framework" can handle by adding custom switches.

As for your code, feel free to add a few more comments: Gijs & Hyde can then review it WRT to integrating it with the ND.
Once that is done, I'll have another look to generalize things and extend MapStructure accordingly (I don't think Philosopher is currently around)
But we should definitely be able to make this an upcoming feature for FG > 3.2

generalizing and refactoring should evolve automatically once we have a few more aircraft using your code - and ideally also at least one GUI dialog.

Gijs wrote in Thu Jul 17, 2014 3:14 pm:ALT-profile is used to draw T/D, T/C etc. Waypoint altitude is displayed (in text) below each waypoint ID on the active route (when input to the route manager). It's visible in your screenshot. See WPT.lcontroller line 43 onwards for the altitude retrieval function.


Technically, we should be able to reuse the same routines for different projections/symbol files, i.e. the data will be identical and probably even be shared. Philosopher once mentioned that he wanted to support reusing controllers for different layers. So it should be possible to extend the framework accordingly.

On the MapStructure side, we'll probably want to add a few features:
  • adding different types of maps
  • supporting vertical projections
  • defining a clipped region for a "sub-screen"

We could then reuse the VSD code to also visualize approaches (e.g. ILS profile compliance etc) - for example, for some kind of instructor console:
Image
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: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Cannot use .setText on SVG text element

Postby omega95 » Thu Jul 17, 2014 7:17 pm

Hooray wrote in Thu Jul 17, 2014 6:32 pm:I suggest you prepare your code so that you can post it here and we can take a look


Alright, so I think I explained what I was doing and replaced (most) numbers that are based on the SVG file, user preferences etc. with variables. There are still some things not complete yet though.

    I'm not sure what the best way is to draw circles for the waypoints - but now that I think of it, it's probably better to load the wpt symbol from an svg file and overlay it. That way, if the VSD (like a Boeing (787) version) has different waypoint symbols, it'll be easy to customize it. Or maybe even use one of the .symbol files.
    The center is not being set properly for speed/path arrow rotation. :(

Other than that, here it is -

Code: Select all
# [Airbus] Vertical Situation Display
# Narendran M (c) 2014

# Scroll to the end of the file for object instantiations

# If you just want a quick and dirty edit/port to your aircraft, just edit the model object names, svg path, switches and props
var objName_capt = 'vsd.l';      # Model object name for captain's side VSD
var objName_fo = 'vsd.r';      # Model object name for first officer's side VSD
var svg_path = '/Aircraft/A380/Models/Instruments/ND/vsd.svg'; # VSG File Path

# It is very important to note that the below switches and props defines will ONLY work on the A380 by theOmegaHangar (http://theomegahangar.flymerlion.org) and other derived aircraft. If you would like to add this to your aircraft, please change the switches and interface properties to connect it to your aircraft!

# Define custom aircraft cockpit switches to be interfaced
var mySwitches = {
   'set_range':          {   path: '/inputs/range-nm'   , value: 10   },
   'toggle_waypoints':      {   path: '/inputs/wpt'         , value: 0   },
   'toggle_constraints':   {   path: '/inputs/cstr'      , value: 0   }
};

# Define interface props and functions to use the flightplan management system and aircraft instrumentation

# A380 Flightplan management system properties
var myProps_A380 = {
   curWptId:   '/flight-management/flightplan/currentWpt',
   wpt_data:    {
      # Change the return properties to suit your custom route manager system
      ident: func(n) {
         return '/flight-management/flightplan/wpt['~n~']/ident';
      },
      latitude: func(n) {
         return '/flight-management/flightplan/wpt['~n~']/latitude';
      },
      longitude: func(n) {
         return '/flight-management/flightplan/wpt['~n~']/longitude';
      },
      alt_cstr: func(n) {
         return '/flight-management/flightplan/wpt['~n~']/altitude';
      }
   },
   num_wpts:         '/flight-management/flightplan/num-wpts',
   altitude_ind:      '/instrumentation/altimeter/indicated-altitude-ft',
   heading_ind:      '/instrumentation/heading-indicator/indicated-heading-deg',
   ap_altitude_set:   '/flight-management/fcu-values/alt',
   vertSpd_ind:      '/instrumentation/vertical-speed-indicator/indicated-speed-kts'
};

# FGRouteManager and generic autopilot system properties
var myProps = {
   curWptId:   '/autopilot/route-manager/current-wp',
   wpt_data:    {
      # Change the return properties to suit your custom route manager system
      ident: func(n) {
         return '/autopilot/route-manager/route/wp['~n~']/id';
      },
      latitude: func(n) {
         return '/autopilot/route-manager/route/wp['~n~']/latitude-deg';
      },
      longitude: func(n) {
         return '/autopilot/route-manager/route/wp['~n~']/longitude-deg';
      },
      alt_cstr: func(n) {
         return '/autopilot/route-manager/route/wp['~n~']/altitude-ft';
      }
   },
   num_wpts:         '/autopilot/route-manager/route/num',
   altitude_ind:      '/instrumentation/altimeter/indicated-altitude-ft',
   heading_ind:      '/instrumentation/heading-indicator/indicated-heading-deg',
   ap_altitude_set:   '/autopilot/settings/target-altitude-ft',
   vertSpd_ind:      '/velocities/vertical-speed-fps'
};

############################## GET ELEVATION DATA ##############################

var get_elevation = func (lat, lon) {
   var info = geodinfo(lat, lon);
   if (info != nil) {var elevation = info[0] * M2FT;}
   else {var elevation = -1.0; }
   return elevation;
};

################################### VSD CLASS ##################################

var vsd = {
   terrain_color:    [0.44, 0.19, 0.09, 0.5],    # A brownish color
   path_color:    [0, 1, 0, 1],            # Bright Green
   cstr_color:    [1, 0, 1, 1],            # Bright Green
   elev_pts: 21,                        # Number of elevation data points
   # Just some variables required by the update() function
   elev_profile: [],
   lastalt:0,
   lastaltset:0,
   alt_ceil: 10000,
   altitude: 0,
   peak: 0,
   # Contants dependent on SVG file
   alt_ceil_px: 181,                     # Pixel length of vertical axis
   max_range_px: 710,                     # Pixel length of horizontal axis
   terr_offset: 22,                     # Offset between start of terrain polygon y and bottom_left corner
   bottom_left: {x:233, y:294},            # {x:x,y:y_max - y} of bottom-left corner of plot area - looks like canvas starts it's y axis from the top going down
   # sym_names: ["aircraft_marker", "speed_arrow", "text_range1", "text_range2", "text_range3", "text_range4", "text_alt1", "text_alt2", "altitude_set"],
   new: func(efis_id, obj_name, switches, interface_props, svg_path) {
      var t = {parents:[vsd]};
      
      # Initialize VSD Display
      t.display = canvas.new({
         "name": "vsdScreen",
         "size": [1024, 320],
         "view": [1024, 320],
         "mipmapping": 1
      });
      
      t.efis_id = efis_id;
      t.switches = switches;
      t.interface_props = interface_props;
      
      # Add placement onto 3D model
      t.display.addPlacement({"node": obj_name});
      
      # Create canvas group
      t.group = t.display.createGroup();         # Group for canvas elements and paths
      t.text = t.display.createGroup();         # Group for waypoints text
      t.terrain = t.group.createChild("path");   # Terrain Polygon
      t.path = t.group.createChild("path");      # Flightplan Path
      t.cstr = t.group.createChild("path");      # Altitude constraints (?)
      
      # Load Vertical Situation Display
      canvas.parsesvg(t.group, svg_path);
      
      setsize(t.elev_profile,t.elev_pts);
      
      # Set cockpit switch listeners
      # Range Numbers
      setlistener("/instrumentation/efis["~t.efis_id~"]"~t.switches['set_range'].path, func(n) {
         var range = n.getValue();
         if(range > 10) {
            t.group.getElementById("text_range1").setText(sprintf("%3.0f",range*0.25));
            t.group.getElementById("text_range2").setText(sprintf("%3.0f",range*0.5));
            t.group.getElementById("text_range3").setText(sprintf("%3.0f",range*0.75));
            t.group.getElementById("text_range4").setText(sprintf("%3.0f",range));
         } else {
            t.group.getElementById("text_range1").setText(sprintf("%1.1f",range*0.25));
            t.group.getElementById("text_range2").setText(sprintf("%1.0f",range*0.5));
            t.group.getElementById("text_range3").setText(sprintf("%1.1f",range*0.75));
            t.group.getElementById("text_range4").setText(sprintf("%1.0f",range));
         }
         t.range = range;
      });
      
      # Autopilot Altitude Setting
      setlistener(t.interface_props.ap_altitude_set, func(n) {
         t.alt_set = n.getValue();
         if((t.alt_set == nil) or (t.alt_set > 2.5*t.alt_ceil)) {
            t.group.getElementById("altitude_set").hide();
         } else {
            t.group.getElementById("altitude_set").show();
         }
         # Move Altitude Setting Line
         t.newSetPos = -t.alt_ceil_px*(t.alt_set/t.alt_ceil);
         t.group.getElementById("altitude_set").setTranslation(0,t.newSetPos-t.lastaltset);
         t.lastaltset = t.newSetPos;
         t.group.getElementById("tgt_altitude").setText(sprintf("%5.0f",t.alt_set));
      });
      
      # Create 2 empty geo.Coord object for waypoint calculations
      t.wpt_this = geo.Coord.new();
      t.wpt_next = geo.Coord.new();

      return t;
   },
   init: func {
      me.UPDATE_INTERVAL = 1;
      me.loopid = 0;
      me.reset();
   },
   update: func {
      # Generate elevation profile
      
      me.altitude = getprop(me.interface_props.altitude_ind);
      if(me.altitude == nil) {
         me.altitude = 0;
      }
      foreach(var alt; [5000, 10000, 20000, 30000, 40000]) {
         if((me.altitude <= alt) and (me.peak <= alt)) {
            me.alt_ceil = alt;
            break;
         }
      }
      
      me.new_markerPos = -me.alt_ceil_px*(me.altitude/me.alt_ceil);
      
      var rangeHdg = [];      # To change the scan course to get vertical profile along the flight path
      var cstrAlts = [];      # Get Constraint altitudes for plotting
      
      # Vertical Flight Path
      if(getprop("/instrumentation/efis["~me.efis_id~"]"~me.switches.toggle_waypoints.path) == 1) {
         var numWpts = getprop(me.interface_props.num_wpts);
         var currWpt = getprop(me.interface_props.curWptId);
         if((numWpts > 1) and (currWpt >= 0)) {
            me.path.del();
            me.text.removeAllChildren();
            me.path = me.group.createChild("path");
            me.path.setColor(me.path_color)
                  .moveTo(me.bottom_left.x,me.bottom_left.y+me.new_markerPos)
                  .setStrokeLineWidth(2)
                  .show();
            me.wpt_this.set_latlon(getprop(me.interface_props.wpt_data.latitude(currWpt)), getprop(me.interface_props.wpt_data.longitude(currWpt)));
            var rteLen = geo.aircraft_position().distance_to(me.wpt_this)*M2NM;
            var brk_next = 0;
            # Calculate distance between waypoints
            for(var id=currWpt; id<numWpts; id=id+1) {
               var alt = getprop(me.interface_props.wpt_data.alt_cstr(id));
               if(alt != nil) {
                  if(rteLen > me.range) {
                     brk_next = 1;
                  }
                  if(alt > 0) {
                     # Plot it if it's in range!
                     me.path.lineTo(me.bottom_left.x + me.max_range_px*(rteLen/me.range), me.bottom_left.y -me.alt_ceil_px*(alt/me.alt_ceil));
                     if(getprop("/instrumentation/efis["~me.efis_id~"]"~me.switches.toggle_constraints.path) == 1) {
                        append(cstrAlts, {range: me.bottom_left.x + me.max_range_px*(rteLen/me.range),   cstr: me.bottom_left.y -me.alt_ceil_px*(alt/me.alt_ceil)});
                     }
                     # Add circle and waypoint ident
                     # FIXME - Figure out the best way of dynamically drawing circles at waypoint OR just load the wpt symbol from an SVG file
                     me.text.createChild("text")
                           .setAlignment("left-bottom")
                           .setColor(me.path_color)
                           .setFontSize(28,1.2)
                           .setTranslation(me.bottom_left.x + 12 + me.max_range_px*(rteLen/me.range), me.bottom_left.y - 12 - me.alt_ceil_px*(alt/me.alt_ceil))
                           .setText(getprop(me.interface_props.wpt_data.ident(id)));
                     if(id<(numWpts-1)) {
                        me.wpt_this.set_latlon(getprop(me.interface_props.wpt_data.latitude(id)), getprop(me.interface_props.wpt_data.longitude(id)));
                        me.wpt_next.set_latlon(getprop(me.interface_props.wpt_data.latitude(id+1)), getprop(me.interface_props.wpt_data.longitude(id+1)));
                        append(rangeHdg, {range: rteLen, course: me.wpt_this.course_to(me.wpt_next)});
                        rteLen = rteLen + me.wpt_this.distance_to(me.wpt_next)*M2NM;
                     }
         # FIXME - This is a little messy, need to clean it up
                  } else {
                     break;
                  }
               } else {
                  break;
               }
               if(brk_next == 1) {
                  break;
               }
            }
         } else {
            me.path.hide();
         }
      } else {
         me.path.hide();
         me.text.removeAllChildren();
      }
      
      # Draw Altitude Constraints
      if(getprop("/instrumentation/efis["~me.efis_id~"]"~me.switches.toggle_constraints.path) == 1) {
         me.cstr.del();
         me.cstr = me.group.createChild("path");
         me.cstr.setColor(me.cstr_color)
               .moveTo(me.bottom_left.x,me.bottom_left.y+me.new_markerPos)
               .setStrokeLineWidth(2)
               .setStrokeDashArray([10, 10, 10, 10, 10])
               .show();
         forindex(var i; cstrAlts) {
            me.cstr.vertTo(cstrAlts[i].cstr).horizTo(cstrAlts[i].range);
         }
      } else {
         me.cstr.hide();
      }
      
         
      var pos = geo.aircraft_position();
      
      # Get terrain profile along the flightplan route if WPT is enabled. If WPT is not enabled, the rangeHdg vector should be empty, so it's just going to get the elevation profile along the indicated aircraft heading
         
      me.peak = 0;
      forindex(var i; me.elev_profile) {
         var check_hdg = getprop(me.interface_props.heading_ind);
         foreach(var wpt; rangeHdg) {
            if(i*(me.range/me.elev_pts) > wpt.range) {
               check_hdg = wpt.course;
            } else {
               break;
            }
         }
         pos.apply_course_distance(check_hdg,(me.range/me.elev_pts)*NM2M);
         var elev = get_elevation(pos.lat(), pos.lon());
         me.elev_profile[i] = elev;
         if(elev > me.peak) {
            me.peak = elev; # Update Peak Point
         }
      }
      # Set Altitude Numbers
      me.terrain.del();
      me.terrain = me.group.createChild("path");
      me.terrain.setColorFill(me.terrain_color).moveTo(me.bottom_left.x,me.bottom_left.y + me.terr_offset);
      
      # Draw Terrain
      forindex(var i; me.elev_profile) {
         me.terrain.lineTo(me.bottom_left.x+(i*(me.max_range_px/(me.elev_pts-1))), me.bottom_left.y - me.alt_ceil_px*(me.elev_profile[i]/me.alt_ceil));
      }
      
      me.terrain.lineTo(me.bottom_left.x+me.max_range_px,me.bottom_left.y+me.terr_offset);
      
      me.group.getElementById("text_alt1").setText(sprintf("%5.0f",me.alt_ceil/2));
      me.group.getElementById("text_alt2").setText(sprintf("%5.0f",me.alt_ceil));
      
      me.group.getElementById("aircraft_marker").setTranslation(0,me.new_markerPos-me.lastalt);
      
      var vs_fps = getprop(me.interface_props.vertSpd_ind);
      if(vs_fps == nil) {
         vs_fps = 0;
      }
      var gs_fps = getprop("/velocities/groundspeed-kt")*1.46667; # KTS to FPS
      if(gs_fps > 60) {
         var fpa = math.atan2(vs_fps, gs_fps);
         # FIXME - something wrong with the center of the speed arrow
         me.group.getElementById("speed_arrow").setTranslation(0,me.new_markerPos-me.lastalt)
                                      .setCenter(me.bottom_left.x + 12,me.bottom_left.y + me.new_markerPos)
                                      .setRotation(-fpa)
                                      .show();         
      } else {
         me.group.getElementById("speed_arrow").hide();
      }
      
      me.lastalt = me.new_markerPos;
      
   },
   reset: func {
      me.loopid += 1;
      me._loop_(me.loopid);
   },
   _loop_: func(id) {
      id = me.loopid or return;
      me.update();
      settimer(func {me._loop_(id); }, me.UPDATE_INTERVAL);
   },
   showDlg: func {
      if(getprop("sim/instrument-options/canvas-popup-enable")) {
          var dlg = canvas.Window.new([320, 100], "dialog");
          dlg.setCanvas(me.display);
      }
   }
};

############################### INSTANTIATE VSDs ###############################

var capt_vsd = vsd.new(0, objName_capt, mySwitches, myProps, svg_path);
var fo_vsd = vsd.new(1, objName_fo, mySwitches, myProps, svg_path);

setlistener("sim/signals/fdm-initialized", func {
   capt_vsd.init();
   fo_vsd.init();
   print("Vertical Situation Displays Initialized");
});


We can probably generalize some things in the WPT/RTE/ALT-profile layers to also support vertical modes


Exactly, if we had a vertical WPT and hard-coded terrain layer (this is tricky as it's dependent on the WPTs) this almost exactly be like the ND. :)

Cheers!
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Cannot use .setText on SVG text element

Postby Hooray » Thu Jul 17, 2014 7:29 pm

I'm not sure what the best way is to draw circles for the waypoints - but now that I think of it, it's probably better to load the wpt symbol from an svg file and overlay it.

I wouldn't spend too much time working on that, MapStructure contains support for caching, so that things will be faster that way - i.e. instead of re-drawing possibly 100 identical symbols/paths, it will draw the symbol just once and then use "instancing" via raster images (texture map lookups) - the Avidyne Entegra R9 developers copied that approach and they were able to get slightly better performance, too - even though they went slightly "overboard" with it, because they're now caching pretty much anything ...

Regarding your code, it will be important to use variables for anything contains hard-coded assumptions about the size of the canvas, the map, scale, and offsets etc - otherwise, the code won't work once someone uses different resolutions/settings etc

Also, it would make sense to adopt MapStructure stylign for things like terrain/path colors etc

Exactly, if we had a vertical WPT and hard-coded terrain layer (this is tricky as it's dependent on the WPTs) this almost exactly be like the ND.

We'll mostly have to split up your code and refactor/generalize it a bit more - have you looked already at creating your own MapStructure layers ?
I guess you could make some first experiments with a TERR/height map layer, while we'll extend MapStructure to support vertical layers, so that your work can be ported more easily.
But the necessary work is not rocket science - even though it helps understanding how to create new layers.

I guess Gijs & Hyde can comment on how they'd like to see it integrated with the ND framework, so that they can optionally reuse the VSD on their aircraft.
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: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Cannot use .setText on SVG text element

Postby Philosopher » Thu Jul 17, 2014 7:34 pm

you know.... vertical+horizontal = short step to 3D projection ;)

I'm semi-back but haven't worked on FG yet..... too busy translating my apps into Latin :P
Philosopher
 
Posts: 1593
Joined: Sun Aug 12, 2012 7:29 pm

Re: Cannot use .setText on SVG text element

Postby Hooray » Fri Jul 18, 2014 4:47 pm

Philosopher wrote in Thu Jul 17, 2014 7:34 pm:you know.... vertical+horizontal = short step to 3D projection ;)


not sure if we'd want to pursue that - while X-Plane does have such a 3D map, it would be kinda awkward to model on top of a 2D drawing API in my opinion - we'd need to encode viewports and manually do stuff that OSG is actually designed to handle - and according to FAA field tests, 3D avionics are generally not as intuitive when compared to having a set of independent 2D avionics (i.e. ND + VSD + PFD). I guess we'll have to reconsider some things once scenery camera can be rendered to a texture, but otherwise Canvas is primarily about 2D drawing, and it would probably not be particularly efficient to re-invent the wheel on top of ShivaVG, given that that the whole thing goes through OSG space either way.

Supporting a few common GIS projections would seem useful though, i.e. integrating Proj4 - and if we really want to create a 3D projection, we'd probably be better off by rendering the scene to a texture and using canvas shaders then to add flight path info that way.
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: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU


Return to Canvas

Who is online

Users browsing this forum: No registered users and 1 guest