zkv1000 / Nasal / map.nas /
Newer Older
724 lines | 26.223kb
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
1
# vim: set foldmethod=marker foldmarker={{{,}}} :
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
2
var mapClass = {
3
# main class for maps {{{
4
    new : func (device) {
5
        var m = { parents : [ mapClass ] };
6
        m.device = device;
7

            
8
        m.device.data.mapview = [
9
            m.device.display.display.get('view[0]'),
10
            m.device.display.display.get('view[1]')
11
        ];
12
        m.device.data.mapsize = [
13
            m.device.display.display.get('size[0]'),
14
            m.device.display.display.get('size[1]')
15
        ];
16
        m.device.data.zoom = 10;
17
        m.device.data.orientation = {
18
            text: 'NORTH UP',
19
            map: 0,
20
            airplane: data.hdg,
21
        };
22
        m.changeZoom();
23
        
24
        m.group = m.device.display.display.createGroup()
25
            .set('clip',
26
                    'rect('
27
                        ~ m.device.data.mapclip.top ~','
28
                        ~ m.device.data.mapclip.right ~','
29
                        ~ m.device.data.mapclip.bottom ~','
30
                        ~ m.device.data.mapclip.left ~')')
31
            .setCenter(
32
                (m.device.data.mapclip.right + m.device.data.mapclip.left) / 2,
33
                (m.device.data.mapclip.bottom + m.device.data.mapclip.top) / 2);
34

            
35
        m.tiles = MapTiles.new(m.device, m.group);
36
        m.navaids = MapNavaids.new(m.device, m.group);
37

            
38
#        m.device.display.display.createGroup().createChild('path')
39
#            .setColor(1,0,0)
40
#            .setColorFill(1,0,0)
41
#            .setStrokeLineWidth(2)
42
#            .moveTo(
43
#                m.device.data.mapclip.left + (m.device.data.mapclip.right-m.device.data.mapclip.left)/2,
44
#                m.device.data.mapclip.top +50)
45
#            .vertTo(
46
#                m.device.data.mapclip.bottom -50)
47
#            .close()
48
#            .moveTo(
49
#                m.device.data.mapclip.left +50,
50
#                m.device.data.mapclip.top + (m.device.data.mapclip.bottom-m.device.data.mapclip.top)/2)
51
#            .horizTo(
52
#                m.device.data.mapclip.right-50)
53
#            .close();
54

            
55
        return m;
56
    },
57
    changeZoom : func (d = 0) {
58
        me.device.data.zoom = math.max(2, math.min(19, me.device.data.zoom + d));
59
        me.device.data['range-nm'] = me.device.display.display.get('view[1]') / 2 * 84.53 * math.cos(data.lat) / math.pow(2, me.device.data.zoom);
60
        me.device.data['range-factor'] = math.pow(2,13 - me.device.data.zoom) * 1.6875;
61
    },
62
    update : func {
63
        if (me.device.data.orientation.text == 'NORTH UP') {
64
            me.device.data.orientation.map = 0;
65
            me.device.data.orientation.airplane = data.hdg;
66
        }
67
        elsif (me.device.data.orientation.text == 'TRK UP') {
68
            if (data.wow) {
69
                me.device.data.orientation.map = -data.hdg;
70
                me.device.data.orientation.airplane = data.hdg;
71
            }
72
            else {
73
                var track = getprop('/orientation/track-deg');
74
                me.device.data.orientation.map = -track;
75
                me.device.data.orientation.airplane = data.hdg;
76
            }
77
        }
78
        elsif (me.device.data.orientation.text == 'DTK UP') {
79
            me.device.data.orientation.map = 0;
80
            me.device.data.orientation.airplane = 0;
81
        }
82
        elsif (me.device.data.orientation.text == 'HDG UP') {
83
            me.device.data.orientation.map = -data.hdg;
84
            me.device.data.orientation.airplane = data.hdg;
85
        }
86

            
87
        me.group.setRotation(me.device.data.orientation.map * D2R);
88

            
89
        me.tiles.update();
90
        me.navaids.update();
91
    },
92
    setVisible : func (v) {
93
        me.tiles.setVisible(v);
94
        me.navaids.setVisible(v);
95
    },
96
};
97
# }}}
98

            
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
99
var MapTiles = {
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
100
# displays maps background from web tiles {{{
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
101
# code from http://wiki.flightgear.org/Canvas_Snippets#A_simple_tile_map
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
102
    new : func (device, group) {
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
103
        var m = { parents: [MapTiles] };
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
104
        m.device = device;
105
        m.display = m.device.display.display;
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
106
        m.tile_size = 256;
107
        m.maps_base = getprop("/sim/fg-home") ~ '/cache/maps';
moves some map infos in data...
Sébastien MARQUE authored on 2017-04-11
108
        m.makeUrl = string.compileTemplate('https://{server}/{type}/{z}/{x}/{y}.png{apikey}');
109
        m.makePath = string.compileTemplate(m.maps_base ~ '/{server}/{type}/{z}/{x}/{y}.png');
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
110
        m.num_tiles = [
get map display size from da...
Sébastien MARQUE authored on 2017-04-18
111
            math.ceil( m.device.data.mapsize[0] / m.tile_size ) + 1,
112
            math.ceil( m.device.data.mapsize[1] / m.tile_size ) + 1
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
113
        ];
114
        m.center_tile_offset = [
115
            (m.num_tiles[0] - 1) / 2,
116
            (m.num_tiles[1] - 1) / 2
117
        ];
makes map available for PFD ...
Sébastien MARQUE authored on 2017-04-19
118
        m.visibility = m.device.role == 'MFD';
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
119
        m.group = group.createChild('group', 'tiles')
get map display size from da...
Sébastien MARQUE authored on 2017-04-18
120
            .setTranslation(
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
121
                    m.device.role == 'MFD' ? (m.device.data.mapview[0] - m.device.data.mapsize[0] + m.device.data.mapclip.left)/2 : -520,
122
                    m.device.role == 'MFD' ? -250 : -45)
makes map available for PFD ...
Sébastien MARQUE authored on 2017-04-19
123
            .setVisible(m.visibility);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
124
        m.tiles = setsize([], m.num_tiles[0]);
125
        m.last_tile = [-1,-1];
moves some map infos in data...
Sébastien MARQUE authored on 2017-04-11
126
        m.last_type = data['tiles-type'];
makes map available for PFD ...
Sébastien MARQUE authored on 2017-04-19
127
        m.initialize_grid();
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
128
        return m;
129
    },
130

            
makes map available for PFD ...
Sébastien MARQUE authored on 2017-04-19
131
    setVisible : func (v) {
132
        if (v != me.visibility) {
133
            me.visibility = v;
134
            me.group.setVisible(v);
135
        }
136
    },
137

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
138
# initialize the map by setting up a grid of raster images
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
139
    initialize_grid : func {
140
        for(var x = 0; x < me.num_tiles[0]; x += 1) {
141
            me.tiles[x] = setsize([], me.num_tiles[1]);
142
            for(var y = 0; y < me.num_tiles[1]; y += 1)
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
143
                me.tiles[x][y] = me.group.createChild('image', 'tile ' ~ x ~ ',' ~ y);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
144
        }
145
    },
146

            
147
# this is the callback that will be regularly called by the timer to update the map
makes map available for PFD ...
Sébastien MARQUE authored on 2017-04-19
148
    update : func {
149
         if (! me.visibility)
150
             return;
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
151

            
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
152
        var n = math.pow(2, me.device.data.zoom);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
153
        var offset = [
put lat/lon in global data s...
Sébastien MARQUE authored on 2017-04-12
154
            n * ((data.lon + 180) / 360) - me.center_tile_offset[0],
155
            (1 - math.ln(math.tan(data.lat * math.pi/180) + 1 / math.cos(data.lat * math.pi/180)) / math.pi) / 2 * n - me.center_tile_offset[1]
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
156
        ];
157
        var tile_index = [int(offset[0]), int(offset[1])];
158

            
159
        var ox = tile_index[0] - offset[0];
160
        var oy = tile_index[1] - offset[1];
161

            
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
162
        for (var x = 0; x < me.num_tiles[0]; x += 1)
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
163
            for(var y = 0; y < me.num_tiles[1]; y += 1)
164
                me.tiles[x][y]
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
165
                    .setTranslation(
166
                        int((ox + x) * me.tile_size + 0.5),
167
                        int((oy + y) * me.tile_size + 0.5));
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
168

            
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
169
        if (tile_index[0] != me.last_tile[0]
170
         or tile_index[1] != me.last_tile[1]
171
         or data['tiles-type'] != me.last_type) {
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
172
            for(var x = 0; x < me.num_tiles[0]; x += 1)
173
                for(var y = 0; y < me.num_tiles[1]; y += 1) {
174
                    var pos = {
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
175
                        z: me.device.data.zoom,
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
176
                        x: int(offset[0] + x),
177
                        y: int(offset[1] + y),
moves some map infos in data...
Sébastien MARQUE authored on 2017-04-11
178
                        type: data['tiles-type'],
179
                        server : data['tiles-server'],
180
                        apikey: data['tiles-apikey'],
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
181
                    };
182

            
183
                    (func {
184
                        var img_path = me.makePath(pos);
185
                        printlog('debug', 'img_path: ', img_path);
186
                        var tile = me.tiles[x][y];
187

            
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
188
                        if (io.stat(img_path) == nil) { # image not found, save in $FG_HOME
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
189
                            var img_url = me.makeUrl(pos);
190
                            printlog('debug', 'requesting ' ~ img_url);
191
                            http.save(img_url, img_path)
192
                                .done(func {printlog('info', 'received image ' ~ img_path); tile.set("src", img_path);})
193
                                .fail(func (r) printlog('warn', 'Failed to get image ' ~ img_path ~ ' ' ~ r.status ~ ': ' ~ r.reason));
194
                        }
195
                        else { # cached image found, reusing
196
                            printlog('debug', 'loading ' ~ img_path);
197
                            tile.set("src", img_path);
198
                        }
199
                    })();
200
                }
201
            me.last_tile = tile_index;
moves some map infos in data...
Sébastien MARQUE authored on 2017-04-11
202
            me.last_type = data['tiles-type'];
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
203
        }
204
    },
205
};
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
206
# }}}
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
207

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
208
# The following is largely inspired from the Extra500 Avidyne Entegra 9 
209
# https://gitlab.com/extra500/extra500.git
210
# Many thanks to authors: Dirk Dittmann and Eric van den Berg
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
211

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
212
var MapIconCache = {
213
# creates at init an icons cache for navaids, airports and airplane {{{
214
    new : func (svgFile) {
215
        var m = { parents:[MapIconCache] };
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
216

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
217
        m._canvas = canvas.new( {
218
            'name': 'MapIconCache',
219
            'size': [512, 512],
220
            'view': [512, 512],
221
            'mipmapping': 1
222
        });
223
        m._canvas.addPlacement( {'type': 'ref'} );
224
        m._canvas.setColorBackground(1,1,1,0);
225
        m._group = m._canvas.createGroup('MapIcons');
226

            
227
        canvas.parsesvg(m._group, data.zkv1000_reldir ~ svgFile);
228

            
229
        m._sourceRectMap = {};
230

            
231
        var icons = [ 'airplane' ];
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
232

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
233
        foreach (var near; [0, 1])
234
            foreach (var surface; [0, 1])
235
                foreach (var tower; [0, 1])
236
                    foreach (var center; tower ? [0, 1] : [ 0 ])
237
                        append(icons, 'Airport_' ~ near ~ surface ~ tower ~ center);
238

            
239
        foreach (var type; ['VOR', 'DME', 'TACAN', 'NDB'])
240
            append(icons, 'Navaid_' ~ type);
241

            
242
        foreach (var i; icons)
243
            m.registerIcon(i);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
244

            
245
        return m;
246
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
247
    registerIcon : func (id) {
248
        me._sourceRectMap[id] = {
249
            'bound' : [],
250
            'size'  : [],
251
        };
252
        var element = me._group.getElementById(id);
253
        if (element != nil) {
254
            me._sourceRectMap[id].bound = element.getTransformedBounds();
255
            # TODO ugly hack ? check for reason!
256
            var top     = 512 - me._sourceRectMap[id].bound[3];
257
            var bottom  = 512 - me._sourceRectMap[id].bound[1];
258
            me._sourceRectMap[id].bound[1] = top;
259
            me._sourceRectMap[id].bound[3] = bottom;
260

            
261
            me._sourceRectMap[id].size = [
262
                me._sourceRectMap[id].bound[2] - me._sourceRectMap[id].bound[0],
263
                me._sourceRectMap[id].bound[3] - me._sourceRectMap[id].bound[1]
264
            ];
265
        }
266
        else {
267
            print('MapIconCache.registerIcon(' ~ id ~ ') fail');
268
        }
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
269
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
270
    getBounds : func (id) {
271
        return me._sourceRectMap[id].bound;
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
272
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
273
    getSize : func (id) {
274
        return me._sourceRectMap[id].size;
275
    },
276
    boundIconToImage : func (id, image, center=1) {
277
        if (!contains(me._sourceRectMap, id)) {
278
            print('MapIconCache.boundIconToImage('~id~') ... no available.');
279
            id = 'Airport_0001';
280
        }
281
        image.setSourceRect(
282
                me._sourceRectMap[id].bound[0],
283
                me._sourceRectMap[id].bound[1],
284
                me._sourceRectMap[id].bound[2],
285
                me._sourceRectMap[id].bound[3],
286
                0);
287
        image.setSize(
288
                me._sourceRectMap[id].size[0],
289
                me._sourceRectMap[id].size[1]);
290
        if (center) {
291
            image.setTranslation(
292
                    -me._sourceRectMap[id].size[0]/2,
293
                    -me._sourceRectMap[id].size[1]/2);
294
        }
295
    },
296
};
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
297

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
298
var mapIconCache = MapIconCache.new('Models/MapIcons.svg');
299
# }}}
300

            
301
var MapAirportItem = {
302
# manage airports items by adding the ID and runways on associated icon {{{
303
    new : func (id) {
304
        var m = {parents:[MapAirportItem]};
305
        m._id = id;
306
        m._can = {
307
            'group' : nil,
308
            'label' : nil,
309
            'image' : nil,
310
            'layout': nil,
311
            'runway': [],
312
        };
313
        m._mapAirportIcon = {
314
            'near'      : 0,
315
            'surface'   : 0,
316
            'tower'     : 0,
317
            'center'    : 0,
318
            'displayed' : 0,
319
            'icon'      : '',
320
        };
321
        return m;
322
    },
323
    create : func (group) {
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
324
        me._can.group = group
325
            .createChild('group', 'airport_' ~ me._id);
326

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
327
        me._can.image = me._can.group.createChild('image', 'airport-image_' ~ me._id)
328
            .setFile(mapIconCache._canvas.getPath())
329
            .setSourceRect(0,0,0,0,0);
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
330

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
331
        me._can.label = me._can.group.createChild('text', 'airport-label_' ~ me._id)
332
            .setDrawMode( canvas.Text.TEXT )
333
            .setTranslation(0, 37)
334
            .setAlignment('center-bottom-baseline')
335
            .setFont('LiberationFonts/LiberationSans-Regular.ttf')
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
336
            .setFontSize(24);
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
337

            
nicer airport label
Sébastien MARQUE authored on 2017-04-18
338
        me._can.label.set('fill','#BACBFB');
339
        me._can.label.set('stroke','#000000');
340

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
341
        me._can.layout = group.createChild('group','airport_layout' ~ me._id);
342
        me._can.layoutIcon = group.createChild('group','airport_layout_Icon' ~ me._id);
343
        return me._can.group;
344
    },
345
    draw : func (apt, mapOptions) {
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
346
        me._mapAirportIcon.near = mapOptions.range > 32 ? 0 : 1;
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
347
        me._mapAirportIcon.surface  = 0;
348
        me._mapAirportIcon.tower    = 0;
349
        me._mapAirportIcon.center   = 0;
350
        me._mapAirportIcon.displayed    = 0;
351

            
352
        # TODO make departure and destination airports specific
353
        var aptInfo = airportinfo(apt.id);
354

            
355
        me._can.layout.removeAllChildren();
356
        me._can.layoutIcon.removeAllChildren();
357

            
358
        me._mapAirportIcon.tower = (size(aptInfo.comms('tower')) > 0);
359
        me._mapAirportIcon.center = me._mapAirportIcon.tower and (size(aptInfo.comms('approach')) > 0);
360

            
361
        foreach (var rwy; keys(aptInfo.runways)) {
362
            var runway = aptInfo.runways[rwy];
363
            me._mapAirportIcon.surface = MAP_RUNWAY_SURFACE[runway.surface] ? 1 : me._mapAirportIcon.surface;
364
            me._mapAirportIcon.displayed = runway.length > mapOptions.runwayLength ? 1 : me._mapAirportIcon.displayed;
365

            
366
            if (mapOptions.range <= 10) {    # drawing real runways
367
                me._can.layout.createChild('path', 'airport-runway-' ~ me._id ~ '-' ~ runway.id)
368
                    .setStrokeLineWidth(7)
369
                    .setColor(1,1,1)
370
                    .setColorFill(1,1,1)
371
                    .setDataGeo([
372
                        canvas.Path.VG_MOVE_TO,
373
                        canvas.Path.VG_LINE_TO,
374
                        canvas.Path.VG_CLOSE_PATH
375
                    ],[
376
                        'N' ~ runway.lat, 'E' ~ runway.lon,
377
                        'N' ~ runway.reciprocal.lat, 'E' ~ runway.reciprocal.lon,
378
                    ]);
379
            }
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
380
            elsif (mapOptions.range <= 32) {     #draw icon runways
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
381
                me._can.layoutIcon.setGeoPosition(apt.lat, apt.lon);
382
                me._can.layoutIcon.createChild('path', 'airport-runway-' ~ me._id ~ '-' ~ runway.id)
383
                    .setStrokeLineWidth(7)
384
                    .setColor(1,1,1)
385
                    .setColorFill(1,1,1)
386
                    .setData([
387
                        canvas.Path.VG_MOVE_TO,
388
                        canvas.Path.VG_LINE_TO,
389
                        canvas.Path.VG_CLOSE_PATH
390
                    ],[
391
                        0, -20,
392
                        0, 20,
393
                    ])
394
                    .setRotation((runway.heading)* D2R);
395
            }
396
        }
397
        me._mapAirportIcon.icon = 'Airport_'
398
            ~ me._mapAirportIcon.near
399
            ~ me._mapAirportIcon.surface
400
            ~ me._mapAirportIcon.tower
401
            ~ me._mapAirportIcon.center;
402

            
403
        if (me._mapAirportIcon.displayed) {
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
404
            me._can.label
405
                .setText(apt.id)
406
                .setRotation(-mapOptions.orientation * D2R);
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
407
            me._can.group.setGeoPosition(apt.lat, apt.lon);
408
            if (mapOptions.range <= 10) {
409
                me._can.image.setVisible(0);
410
                me._can.layout.setVisible(1);
411
            }
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
412
            elsif (mapOptions.range <= 32) {
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
413
                mapIconCache.boundIconToImage(me._mapAirportIcon.icon, me._can.image);
414
                me._can.image.setVisible(1);
415
                me._can.layout.setVisible(1);
416
            }
417
            else {
418
                mapIconCache.boundIconToImage(me._mapAirportIcon.icon, me._can.image);
419
                me._can.layout.setVisible(0);
420
                me._can.image.setVisible(1);
421
            }
422
            me._can.group.setVisible(1);
423
        }
424
        return me._mapAirportIcon.displayed;
425
    },
426
    update : func (mapOptions) {
427
        if (mapOptions.range <= 10) { }
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
428
        elsif (mapOptions.range <= 32)
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
429
            me._can.layoutIcon.setRotation(-mapOptions.orientation * D2R);
430
        else { }
431
    },
432
    setVisible : func (visibility) {
433
        me._can.group.setVisible(visibility);
434
        me._can.layout.setVisible(visibility);
435
        me._can.image.setVisible(visibility);
436
        me._can.layoutIcon.setVisible(visibility);
437
    },
438
};
439
# }}}
440

            
441
var MapNavaidItem = {
442
# manage navaids items by adding ID in the icon {{{
443
    new : func (id, type) {
444
        var m = {parents:[MapNavaidItem]};
445
        m._id = id;
446
        m._type = type;
447
        m._can = {
448
            'group' : nil,
449
            'label' : nil,
450
            'image' : nil,
451
        };
452
        return m;
453
    },
454
    create : func (group) {
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
455
        me._can.group = group
456
            .createChild('group', me._type ~ '_' ~ me._id);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
457

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
458
        me._can.image = me._can.group.createChild('image', me._type ~ '-image_' ~ me._id)
459
            .setFile(mapIconCache._canvas.getPath())
460
            .setSourceRect(0,0,0,0,0);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
461

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
462
        me._can.label = me._can.group.createChild('text', me._type ~ '-label_' ~ me._id)
463
            .setDrawMode( canvas.Text.TEXT )
464
            .setTranslation(0,42)
465
            .setAlignment('center-bottom-baseline')
466
            .setFont('LiberationFonts/LiberationSans-Regular.ttf')
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
467
            .setFontSize(24);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
468

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
469
        me._can.label.set('fill','#BACBFB');
470
        me._can.label.set('stroke','#000000');
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
471

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
472
        return me._can.group;
473
    },
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
474
    setData : func (navaid, type, mapOptions) {
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
475
        mapIconCache.boundIconToImage('Navaid_' ~ type, me._can.image);
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
476
        me._can.label
477
            .setText(navaid.id)
478
            .setRotation(-mapOptions.orientation * D2R);
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
479
        me._can.group.setGeoPosition(navaid.lat, navaid.lon);
480
    },
481
    setVisible : func (visibility) {
482
        me._can.group.setVisible(visibility);
483
    },
484
};
485
# }}}
486

            
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
487
var MapAirplaneItem = {
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
488
# set airplane on ND {{{
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
489
    new : func {
490
        var m = {parents:[MapAirplaneItem]};
491
        m._can = {
492
            'group' : nil,
493
            'image' : nil,
494
        };
495
        return m;
496
    },
497
    create : func (group) {
498
        me._can.group = group
499
            .createChild('group', 'airplane');
500
        me._can.image = me._can.group.createChild('image', 'airplane-image')
501
            .setFile(mapIconCache._canvas.getPath())
502
            .setSourceRect(0,0,0,0,0);
503
        return me._can.group;
504
    },
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
505
    setData : func (orientation) {
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
506
        mapIconCache.boundIconToImage('airplane', me._can.image);
507
        me._can.group
508
            .setGeoPosition(data.lat, data.lon)
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
509
            .setRotation(orientation * D2R);
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
510
    },
511
    setVisible : func (visibility) {
512
        me._can.group.setVisible(visibility);
513
    },
514
};
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
515
# }}}
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
516

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
517
var MAP_RUNWAY_SURFACE =  {0:0, 1:1, 2:1, 3:0, 4:0, 5:0, 6:1, 7:1, 8:0, 9:0, 10:0, 11:0, 12:0};
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
518
var MAP_RUNWAY_AT_RANGE = func (range) {
519
    if (range < 40) return 0;
520
    if (range < 50) return 250;
521
    if (range < 80) return 500;
522
    if (range < 160) return 1000;
523
    if (range < 240) return 3000;
524
    return 3000;
525
}
526
var MAP_TXRANGE_VOR = func (range) {
527
    if (range < 40) return 0;
528
    if (range < 50) return 20;
529
    if (range < 80) return 25;
530
    if (range < 160) return 30;
531
    if (range < 240) return 50;
532
    return 100;
533
}
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
534
####
535
# Declutter
536
#   land
537
#       0 : 'Terrain'
538
#       1 : 'Political boundaries'
539
#       2 : 'River/Lakes/Oceans'
540
#       3 : 'Roads'
541
#   Nav
542
#       0 : 'Airspace'
543
#       1 : 'Victor/Jet airways'
544
#       2 : 'Obstacles'
545
#       3 : 'Navaids'
546

            
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
547
var MapNavaids = {
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
548
# the layer to show navaids, airports and airplane symbol {{{
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
549
    new : func (device, group) {
550
        var m = {parents : [MapNavaids]};
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
551

            
552
        m._model = nil;
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
553
        m.device = device;
makes map available for PFD ...
Sébastien MARQUE authored on 2017-04-19
554
        m._visibility = m.device.role == 'MFD';
555

            
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
556
        m._group = group.createChild('map', 'MFD map')
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
557
            .setTranslation(
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
558
                m.device.role == 'MFD' ? (m.device.data.mapview[0] + m.device.data.mapclip.left)/2 : 120,
559
                m.device.role == 'MFD' ? 400 : 600)
makes map available for PFD ...
Sébastien MARQUE authored on 2017-04-19
560
            .setVisible(m._visibility);
561
            m._group._node
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
562
                .getNode('range', 1).setDoubleValue(m.device.data['range-factor']);
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
563

            
564
        m._can = {};
565
        m._cache = {};
566
        foreach (var n; ['airport', 'VOR', 'TACAN', 'NDB', 'DME']) {
567
            m._can[n] = m._group.createChild('group', n);
568
            m._cache[n] = {
569
                'data' : [],
570
                'index' : 0,
571
                'max' : 100,
572
            };
573
        }
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
574
        m._can['airplane'] = m._group.createChild('group', 'airplane');
575
        m._cache['airplane'] = {
576
            displayed : 0,
577
            item : nil,
578
        };
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
579

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
580
        m._mapOptions = {
581
            declutterLand : 3,
582
            declutterNAV  : 3,
583
            lightning     : 0,
584
            reports       : 0,
585
            overlay       : 0,
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
586
            range         : m.device.data['range-nm'],
587
            rangeLow      : m.device.data['range-nm'] / 2,
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
588
            runwayLength  : -1,
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
589
            orientation   : m.device.data.orientation.map,
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
590
        };
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
591

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
592
        m._results = nil;
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
593

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
594
        return m;
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
595
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
596
    update : func {
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
597
        me._group._node.getNode('ref-lat', 1).setDoubleValue(data.lat);
598
        me._group._node.getNode('ref-lon', 1).setDoubleValue(data.lon);
599

            
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
600
        me._group._node
601
            .getNode('range', 1).setDoubleValue(me.device.data['range-factor']);
602
        me._mapOptions.orientation = me.device.data.orientation.map;
603

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
604
        if (me._visibility == 1) {
605
            me.loadAirport();
606
            foreach (var n; ['VOR', 'TACAN', 'NDB', 'DME'])
607
                me.loadNavaid(n);
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
608
            me.loadAirplane();
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
609
        }
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
610
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
611
    _onVisibilityChange : func {
612
        me._group.setVisible(me._visibility);
613
    },
614
    setMapOptions : func (mapOptions) {
615
        me._mapOptions = mapOptions;
616
        me.update();
617
    },
618
    updateOrientation : func (value) {
619
        me._mapOptions.orientation = value;
620
        for (var i = 0 ; i < me._cache.airport.index ; i +=1) {
621
            item = me._cache.airport.data[i];
622
            item.update(me._mapOptions);
commit initial
Sébastien MARQUE authored on 2017-03-07
623
        }
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
624
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
625
    setRange : func (range=100) {
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
626
        me._mapOptions.range = me.device.data['range-nm'];
627
        me._mapOptions.rangeLow = me._mapOptions.range/2;
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
628
        me.update();
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
629
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
630
    setRotation : func (deg) {
631
        me._group.setRotation(deg * D2R);
632
    },
633
    setVisible : func (v) {
634
        if (me._visibility != v) {
635
            me._visibility = v;
636
            me._onVisibilityChange();
637
        }
638
    },
639
    _onVisibilityChange : func {
640
        me._group.setVisible(me._visibility);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
641
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
642
    # positioned.findWithinRange : any, fix, vor, ndb, ils, dme, tacan
643

            
644
    loadAirport : func {
645
        me._cache.airport.index = 0;
646
        var results = positioned.findWithinRange(me._mapOptions.range * 2.5, 'airport');
647
        var item = nil;
648

            
649
        if (me._mapOptions.declutterNAV >= 2)
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
650
            me._mapOptions.runwayLength = MAP_RUNWAY_AT_RANGE(me._mapOptions.range);
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
651
        elsif (me._mapOptions.declutterNAV >= 1)
652
            me._mapOptions.runwayLength = 2000;
653
        else
654
            me._mapOptions.runwayLength = 3000;
655

            
656
        if (me._mapOptions.runwayLength >= 0) {
657
            foreach (var apt; results) {
658
                if (me._cache.airport.index >= me._cache.airport.max )
659
                    break;
660

            
661
                if (size(me._cache.airport.data) > me._cache.airport.index)
662
                    item = me._cache.airport.data[me._cache.airport.index];
663
                else {
664
                    item = MapAirportItem.new(me._cache.airport.index);
665
                    item.create(me._can.airport);
666
                    append(me._cache.airport.data, item);
667
                }
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
668

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
669
                if (item.draw(apt, me._mapOptions)) {
670
                    item.setVisible(1);
671
                    me._cache.airport.index += 1;
672
                }
673
            }
674
        }
675

            
676
        for (var i = me._cache.airport.index ; i < size(me._cache.airport.data) ; i +=1) {
677
            item = me._cache.airport.data[i];
678
            item.setVisible(0);
679
        }
680
    },
681
    loadNavaid : func (type) {
682
        me._cache[type].index = 0;
683
        if (me._mapOptions.declutterNAV >= 3) { # TODO test for DME and NDB range < 100nm
684
            var range = me._mapOptions.range * 2.5;
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
685
            var txRange = MAP_TXRANGE_VOR(me._mapOptions.range);
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
686
            var results = positioned.findWithinRange(range, type);
687
            var item = nil;
688
            foreach (var n; results) {
689
                if (n.range_nm < txRange)
690
                    break;
691

            
692
                if (me._cache[type].index >= me._cache[type].max )
693
                    break;
694

            
695
                if (size(me._cache[type].data) > me._cache[type].index) {
696
                    item = me._cache[type].data[me._cache[type].index];
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
697
                    item.setData(n, type, me._mapOptions);
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
698
                }
699
                else {
700
                    item = MapNavaidItem.new(me._cache[type].index, type);
701
                    item.create(me._can[type]);
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
702
                    item.setData(n, type, me._mapOptions);
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
703
                    append(me._cache[type].data, item);
704
                }
705
                item.setVisible(1);
706
                me._cache[type].index += 1;
707
            }
708
        }
709
        for (var i = me._cache[type].index ; i < size(me._cache[type].data) ; i +=1) {
710
            item = me._cache[type].data[i];
711
            item.setVisible(0);
commit initial
Sébastien MARQUE authored on 2017-03-07
712
        }
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
713
    },
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
714
    loadAirplane : func {
715
        if (!me._cache.airplane.displayed) {
716
            me._cache.airplane.item = MapAirplaneItem.new();
717
            me._cache.airplane.item.create(me._can['airplane']);
718
            me._cache.airplane.displayed = 1;
719
        }
massive code reorganisation ...
Sébastien MARQUE authored on 2017-05-01
720
        me._cache.airplane.item.setData(me.device.data.orientation.airplane);
navaids displayed with corre...
Sébastien MARQUE authored on 2017-04-18
721
        me._cache.airplane.item.setVisible(1);
722
    },
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
723
};
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
724
# }}}