zkv1000 / Nasal / map.nas /
Newer Older
549 lines | 20.107kb
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
1
# vim: set foldmethod=marker foldmarker={{{,}}} :
2
var MapTiles = {
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
3
# displays maps background from web tiles {{{
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
4
# code from http://wiki.flightgear.org/Canvas_Snippets#A_simple_tile_map
5
    new : func (display) {
6
        var m = { parents: [MapTiles] };
7
        m.display = display;
8
        m.tile_size = 256;
9
        m.zoom = 10;
10
        m.maps_base = getprop("/sim/fg-home") ~ '/cache/maps';
moves some map infos in data...
Sébastien MARQUE authored on 2017-04-11
11
        m.makeUrl = string.compileTemplate('https://{server}/{type}/{z}/{x}/{y}.png{apikey}');
12
        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
13
        m.num_tiles = [
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
14
            math.ceil( m.display.get('view[0]') / m.tile_size ) + 1,
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
15
            math.ceil( m.display.get('view[1]') / m.tile_size ) + 1
16
        ];
17
        m.center_tile_offset = [
18
            (m.num_tiles[0] - 1) / 2,
19
            (m.num_tiles[1] - 1) / 2
20
        ];
maps centered by group (for ...
Sébastien MARQUE authored on 2017-04-13
21
        m.group = m.display.createGroup()
22
            .setCenter(
23
                    m.display.get('view[0]') / 2,
24
                    m.display.get('view[1]') / 2
25
            );
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
26
        m.tiles = setsize([], m.num_tiles[0]);
27
        m.last_tile = [-1,-1];
moves some map infos in data...
Sébastien MARQUE authored on 2017-04-11
28
        m.last_type = data['tiles-type'];
smoother map moves
Sébastien MARQUE authored on 2017-04-13
29
        m.update_timer = maketimer(1, m, m.updateTiles);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
30
        return m;
31
    },
32

            
33
# Simple user interface (Buttons for zoom and label for displaying it)
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
34
    changeZoom : func (d) {
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
35
        me.zoom = math.max(2, math.min(19, me.zoom + d));
36
        call(me.updateTiles, [], me);
37
    },
38

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
39
# initialize the map by setting up a grid of raster images
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
40
    initialize_grid : func {
41
        for(var x = 0; x < me.num_tiles[0]; x += 1) {
42
            me.tiles[x] = setsize([], me.num_tiles[1]);
43
            for(var y = 0; y < me.num_tiles[1]; y += 1)
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
44
                me.tiles[x][y] = me.group.createChild('image', 'tile ' ~ x ~ ',' ~ y);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
45
        }
46
    },
47

            
48
# this is the callback that will be regularly called by the timer to update the map
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
49
    updateTiles : func {
put lat/lon in global data s...
Sébastien MARQUE authored on 2017-04-12
50
#        me.group.setRotation(-data.hdg * D2R);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
51

            
52
        var n = math.pow(2, me.zoom);
53
        var offset = [
put lat/lon in global data s...
Sébastien MARQUE authored on 2017-04-12
54
            n * ((data.lon + 180) / 360) - me.center_tile_offset[0],
55
            (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
56
        ];
57
        var tile_index = [int(offset[0]), int(offset[1])];
58

            
59
        var ox = tile_index[0] - offset[0];
60
        var oy = tile_index[1] - offset[1];
61

            
62
        for(var x = 0; x < me.num_tiles[0]; x += 1)
63
            for(var y = 0; y < me.num_tiles[1]; y += 1)
64
                me.tiles[x][y]
65
                    .setTranslation(int((ox + x) * me.tile_size + 0.5), int((oy + y) * me.tile_size + 0.5));
66

            
67
        if(    tile_index[0] != me.last_tile[0]
68
                or tile_index[1] != me.last_tile[1]
moves some map infos in data...
Sébastien MARQUE authored on 2017-04-11
69
                or data['tiles-type'] != me.last_type ) {
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
70
            for(var x = 0; x < me.num_tiles[0]; x += 1)
71
                for(var y = 0; y < me.num_tiles[1]; y += 1) {
72
                    var pos = {
73
                        z: me.zoom,
74
                        x: int(offset[0] + x),
75
                        y: int(offset[1] + y),
moves some map infos in data...
Sébastien MARQUE authored on 2017-04-11
76
                        type: data['tiles-type'],
77
                        server : data['tiles-server'],
78
                        apikey: data['tiles-apikey'],
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
79
                    };
80

            
81
                    (func {
82
                        var img_path = me.makePath(pos);
83
                        printlog('debug', 'img_path: ', img_path);
84
                        var tile = me.tiles[x][y];
85

            
86
                        if( io.stat(img_path) == nil ) { # image not found, save in $FG_HOME
87
                            var img_url = me.makeUrl(pos);
88
                            printlog('debug', 'requesting ' ~ img_url);
89
                            http.save(img_url, img_path)
90
                                .done(func {printlog('info', 'received image ' ~ img_path); tile.set("src", img_path);})
91
                                .fail(func (r) printlog('warn', 'Failed to get image ' ~ img_path ~ ' ' ~ r.status ~ ': ' ~ r.reason));
92
                        }
93
                        else { # cached image found, reusing
94
                            printlog('debug', 'loading ' ~ img_path);
95
                            tile.set("src", img_path);
96
                        }
97
                    })();
98
                }
99
            me.last_tile = tile_index;
moves some map infos in data...
Sébastien MARQUE authored on 2017-04-11
100
            me.last_type = data['tiles-type'];
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
101
        }
102
    },
103

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
104
    del : func {
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
105
        me.update_timer.stop();
106
        call(canvas.Window.del, [], me);
107
    },
108
};
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
109
# }}}
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
110

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

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

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
120
        m._canvas = canvas.new( {
121
            'name': 'MapIconCache',
122
            'size': [512, 512],
123
            'view': [512, 512],
124
            'mipmapping': 1
125
        });
126
        m._canvas.addPlacement( {'type': 'ref'} );
127
        m._canvas.setColorBackground(1,1,1,0);
128
        m._group = m._canvas.createGroup('MapIcons');
129

            
130
        canvas.parsesvg(m._group, data.zkv1000_reldir ~ svgFile);
131

            
132
        m._sourceRectMap = {};
133

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

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
136
        foreach (var near; [0, 1])
137
            foreach (var surface; [0, 1])
138
                foreach (var tower; [0, 1])
139
                    foreach (var center; tower ? [0, 1] : [ 0 ])
140
                        append(icons, 'Airport_' ~ near ~ surface ~ tower ~ center);
141

            
142
        foreach (var type; ['VOR', 'DME', 'TACAN', 'NDB'])
143
            append(icons, 'Navaid_' ~ type);
144

            
145
        foreach (var i; icons)
146
            m.registerIcon(i);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
147

            
148
        return m;
149
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
150
    registerIcon : func (id) {
151
        me._sourceRectMap[id] = {
152
            'bound' : [],
153
            'size'  : [],
154
        };
155
        var element = me._group.getElementById(id);
156
        if (element != nil) {
157
            me._sourceRectMap[id].bound = element.getTransformedBounds();
158
            # TODO ugly hack ? check for reason!
159
            var top     = 512 - me._sourceRectMap[id].bound[3];
160
            var bottom  = 512 - me._sourceRectMap[id].bound[1];
161
            me._sourceRectMap[id].bound[1] = top;
162
            me._sourceRectMap[id].bound[3] = bottom;
163

            
164
            me._sourceRectMap[id].size = [
165
                me._sourceRectMap[id].bound[2] - me._sourceRectMap[id].bound[0],
166
                me._sourceRectMap[id].bound[3] - me._sourceRectMap[id].bound[1]
167
            ];
168
        }
169
        else {
170
            print('MapIconCache.registerIcon(' ~ id ~ ') fail');
171
        }
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
172
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
173
    getBounds : func (id) {
174
        return me._sourceRectMap[id].bound;
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
175
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
176
    getSize : func (id) {
177
        return me._sourceRectMap[id].size;
178
    },
179
    boundIconToImage : func (id, image, center=1) {
180
        if (!contains(me._sourceRectMap, id)) {
181
            print('MapIconCache.boundIconToImage('~id~') ... no available.');
182
            id = 'Airport_0001';
183
        }
184
        image.setSourceRect(
185
                me._sourceRectMap[id].bound[0],
186
                me._sourceRectMap[id].bound[1],
187
                me._sourceRectMap[id].bound[2],
188
                me._sourceRectMap[id].bound[3],
189
                0);
190
        image.setSize(
191
                me._sourceRectMap[id].size[0],
192
                me._sourceRectMap[id].size[1]);
193
        if (center) {
194
            image.setTranslation(
195
                    -me._sourceRectMap[id].size[0]/2,
196
                    -me._sourceRectMap[id].size[1]/2);
197
        }
198
    },
199
};
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
200

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

            
204
var MapAirportItem = {
205
# manage airports items by adding the ID and runways on associated icon {{{
206
    new : func (id) {
207
        var m = {parents:[MapAirportItem]};
208
        m._id = id;
209
        m._can = {
210
            'group' : nil,
211
            'label' : nil,
212
            'image' : nil,
213
            'layout': nil,
214
            'runway': [],
215
        };
216
        m._mapAirportIcon = {
217
            'near'      : 0,
218
            'surface'   : 0,
219
            'tower'     : 0,
220
            'center'    : 0,
221
            'displayed' : 0,
222
            'icon'      : '',
223
        };
224
        return m;
225
    },
226
    create : func (group) {
227
        me._can.group = group.createChild('group', 'airport_' ~ me._id);
228
        me._can.image = me._can.group.createChild('image', 'airport-image_' ~ me._id)
229
            .setFile(mapIconCache._canvas.getPath())
230
            .setSourceRect(0,0,0,0,0);
231
        me._can.label = me._can.group.createChild('text', 'airport-label_' ~ me._id)
232
            .setDrawMode( canvas.Text.TEXT )
233
            .setTranslation(0, 37)
234
            .setAlignment('center-bottom-baseline')
235
            .setFont('LiberationFonts/LiberationSans-Regular.ttf')
236
            .setFontSize(32);
237

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

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
241
        me._can.layout = group.createChild('group','airport_layout' ~ me._id);
242
        me._can.layoutIcon = group.createChild('group','airport_layout_Icon' ~ me._id);
243
        return me._can.group;
244
    },
245
    draw : func (apt, mapOptions) {
246
        me._mapAirportIcon.near = mapOptions.range > 30 ? 0 : 1;
247
        me._mapAirportIcon.surface  = 0;
248
        me._mapAirportIcon.tower    = 0;
249
        me._mapAirportIcon.center   = 0;
250
        me._mapAirportIcon.displayed    = 0;
251

            
252
        # TODO make departure and destination airports specific
253
        var aptInfo = airportinfo(apt.id);
254

            
255
        me._can.layout.removeAllChildren();
256
        me._can.layoutIcon.removeAllChildren();
257

            
258
        me._mapAirportIcon.tower = (size(aptInfo.comms('tower')) > 0);
259
        me._mapAirportIcon.center = me._mapAirportIcon.tower and (size(aptInfo.comms('approach')) > 0);
260

            
261
        foreach (var rwy; keys(aptInfo.runways)) {
262
            var runway = aptInfo.runways[rwy];
263
            me._mapAirportIcon.surface = MAP_RUNWAY_SURFACE[runway.surface] ? 1 : me._mapAirportIcon.surface;
264
            me._mapAirportIcon.displayed = runway.length > mapOptions.runwayLength ? 1 : me._mapAirportIcon.displayed;
265

            
266
            if (mapOptions.range <= 10) {    # drawing real runways
267
                me._can.layout.createChild('path', 'airport-runway-' ~ me._id ~ '-' ~ runway.id)
268
                    .setStrokeLineWidth(7)
269
                    .setColor(1,1,1)
270
                    .setColorFill(1,1,1)
271
                    .setDataGeo([
272
                        canvas.Path.VG_MOVE_TO,
273
                        canvas.Path.VG_LINE_TO,
274
                        canvas.Path.VG_CLOSE_PATH
275
                    ],[
276
                        'N' ~ runway.lat, 'E' ~ runway.lon,
277
                        'N' ~ runway.reciprocal.lat, 'E' ~ runway.reciprocal.lon,
278
                    ]);
279
            }
280
            elsif (mapOptions.range <= 30) {     #draw icon runways
281
                me._can.layoutIcon.setGeoPosition(apt.lat, apt.lon);
282
                me._can.layoutIcon.createChild('path', 'airport-runway-' ~ me._id ~ '-' ~ runway.id)
283
                    .setStrokeLineWidth(7)
284
                    .setColor(1,1,1)
285
                    .setColorFill(1,1,1)
286
                    .setData([
287
                        canvas.Path.VG_MOVE_TO,
288
                        canvas.Path.VG_LINE_TO,
289
                        canvas.Path.VG_CLOSE_PATH
290
                    ],[
291
                        0, -20,
292
                        0, 20,
293
                    ])
294
                    .setRotation((runway.heading)* D2R);
295
            }
296
        }
297
        me._mapAirportIcon.icon = 'Airport_'
298
            ~ me._mapAirportIcon.near
299
            ~ me._mapAirportIcon.surface
300
            ~ me._mapAirportIcon.tower
301
            ~ me._mapAirportIcon.center;
302

            
303
        if (me._mapAirportIcon.displayed) {
304
            me._can.label.setText(apt.id);
305
            me._can.group.setGeoPosition(apt.lat, apt.lon);
306
            if (mapOptions.range <= 10) {
307
                me._can.image.setVisible(0);
308
                me._can.layout.setVisible(1);
309
            }
310
            elsif (mapOptions.range <= 30) {
311
                mapIconCache.boundIconToImage(me._mapAirportIcon.icon, me._can.image);
312
                me._can.image.setVisible(1);
313
                me._can.layout.setVisible(1);
314
            }
315
            else {
316
                mapIconCache.boundIconToImage(me._mapAirportIcon.icon, me._can.image);
317
                me._can.layout.setVisible(0);
318
                me._can.image.setVisible(1);
319
            }
320
            me._can.group.setVisible(1);
321
        }
322
        return me._mapAirportIcon.displayed;
323
    },
324
    update : func (mapOptions) {
325
        if (mapOptions.range <= 10) { }
326
        elsif (mapOptions.range <= 30)
327
            me._can.layoutIcon.setRotation(-mapOptions.orientation * D2R);
328
        else { }
329
    },
330
    setVisible : func (visibility) {
331
        me._can.group.setVisible(visibility);
332
        me._can.layout.setVisible(visibility);
333
        me._can.image.setVisible(visibility);
334
        me._can.layoutIcon.setVisible(visibility);
335
    },
336
};
337
# }}}
338

            
339
var MapNavaidItem = {
340
# manage navaids items by adding ID in the icon {{{
341
    new : func (id, type) {
342
        var m = {parents:[MapNavaidItem]};
343
        m._id = id;
344
        m._type = type;
345
        m._can = {
346
            'group' : nil,
347
            'label' : nil,
348
            'image' : nil,
349
        };
350
        return m;
351
    },
352
    create : func (group) {
353
        me._can.group = group.createChild('group', me._type ~ '_' ~ me._id);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
354

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

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
359
        me._can.label = me._can.group.createChild('text', me._type ~ '-label_' ~ me._id)
360
            .setDrawMode( canvas.Text.TEXT )
361
            .setTranslation(0,42)
362
            .setAlignment('center-bottom-baseline')
363
            .setFont('LiberationFonts/LiberationSans-Regular.ttf')
364
            .setFontSize(32);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
365

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

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
369
        return me._can.group;
370
    },
371
    setData : func (navaid, type) {
372
        mapIconCache.boundIconToImage('Navaid_' ~ type, me._can.image);
373
        me._can.label.setText(navaid.id);
374
        me._can.group.setGeoPosition(navaid.lat, navaid.lon);
375
    },
376
    setVisible : func (visibility) {
377
        me._can.group.setVisible(visibility);
378
    },
379
};
380
# }}}
381

            
382
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};
383
var MAP_RUNWAY_AT_RANGE = {2:0, 4:0, 10:0, 20:0, 30:0, 40:250, 50:500, 80:1000, 160:2000, 240:3000}; # TODO: make it compatible with tiles zoom level
384
var MAP_TXRANGE_VOR     = {2:0, 4:0, 10:0, 20:0, 30:0, 40:20,  50:25,  80:30,   160:50,   240:100}; # TODO: make it compatible with tiles zoom level
385
####
386
# Declutter
387
#   land
388
#       0 : 'Terrain'
389
#       1 : 'Political boundaries'
390
#       2 : 'River/Lakes/Oceans'
391
#       3 : 'Roads'
392
#   Nav
393
#       0 : 'Airspace'
394
#       1 : 'Victor/Jet airways'
395
#       2 : 'Obstacles'
396
#       3 : 'Navaids'
397

            
398
var PositionedLayer = {
399
# the layer to show navaids, airports and airplane symbol {{{
400
    new : func (display) {
401
        var m = {parents : [PositionedLayer]};
402

            
403
        m._model = nil;
404
        m._group = display.createGroup().createChild('map', 'MFD map');
405

            
406
        m._can = {};
407
        m._cache = {};
408
        foreach (var n; ['airport', 'VOR', 'TACAN', 'NDB', 'DME']) {
409
            m._can[n] = m._group.createChild('group', n);
410
            m._cache[n] = {
411
                'data' : [],
412
                'index' : 0,
413
                'max' : 100,
414
            };
415
        }
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
416

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
417
        m._mapOptions = {
418
            declutterLand : 3,
419
            declutterNAV  : 3,
420
            lightning     : 0,
421
            reports       : 0,
422
            overlay       : 0,
423
            range         : 30,
424
            rangeLow      : 15,
425
            runwayLength  : -1,
426
            orientation   : 0,
427
        };
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
428

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
429
        m._results = nil;
430
        m._timer = maketimer(600, m, PositionedLayer.update);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
431

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
432
        m._visibility = 0;
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
433

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
434
        return m;
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
435
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
436
    update : func {
437
        if (me._visibility == 1) {
438
            me.loadAirport();
439
            foreach (var n; ['VOR', 'TACAN', 'NDB', 'DME'])
440
                me.loadNavaid(n);
441
        }
442
        #TODO compute from actual speed (220 = Vne extra500)
443
        me._timer.restart(me._mapOptions.range/(220/3600));
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
444
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
445
    _onVisibilityChange : func {
446
        me._group.setVisible(me._visibility);
447
    },
448
    setMapOptions : func (mapOptions) {
449
        me._mapOptions = mapOptions;
450
        me.update();
451
    },
452
    updateOrientation : func (value) {
453
        me._mapOptions.orientation = value;
454
        for (var i = 0 ; i < me._cache.airport.index ; i +=1) {
455
            item = me._cache.airport.data[i];
456
            item.update(me._mapOptions);
commit initial
Sébastien MARQUE authored on 2017-03-07
457
        }
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
458
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
459
    setRange : func (range=100) {
460
        me._mapOptions.range = range;
461
        me._mapOptions.rangeLow = range/2;
462
        me.update();
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
463
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
464
    setRotation : func (deg) {
465
        me._group.setRotation(deg * D2R);
466
    },
467
    setVisible : func (v) {
468
        if (me._visibility != v) {
469
            me._visibility = v;
470
            me._onVisibilityChange();
471
        }
472
    },
473
    _onVisibilityChange : func {
474
        me._group.setVisible(me._visibility);
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
475
    },
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
476
    # positioned.findWithinRange : any, fix, vor, ndb, ils, dme, tacan
477

            
478
    loadAirport : func {
479
        me._cache.airport.index = 0;
480
        var results = positioned.findWithinRange(me._mapOptions.range * 2.5, 'airport');
481
        var item = nil;
482

            
483
        if (me._mapOptions.declutterNAV >= 2)
484
            me._mapOptions.runwayLength = MAP_RUNWAY_AT_RANGE[me._mapOptions.range];
485
        elsif (me._mapOptions.declutterNAV >= 1)
486
            me._mapOptions.runwayLength = 2000;
487
        else
488
            me._mapOptions.runwayLength = 3000;
489

            
490
        if (me._mapOptions.runwayLength >= 0) {
491
            foreach (var apt; results) {
492
                if (me._cache.airport.index >= me._cache.airport.max )
493
                    break;
494

            
495
                if (size(me._cache.airport.data) > me._cache.airport.index)
496
                    item = me._cache.airport.data[me._cache.airport.index];
497
                else {
498
                    item = MapAirportItem.new(me._cache.airport.index);
499
                    item.create(me._can.airport);
500
                    append(me._cache.airport.data, item);
501
                }
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
502

            
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
503
                if (item.draw(apt, me._mapOptions)) {
504
                    item.setVisible(1);
505
                    me._cache.airport.index += 1;
506
                }
507
            }
508
        }
509

            
510
        for (var i = me._cache.airport.index ; i < size(me._cache.airport.data) ; i +=1) {
511
            item = me._cache.airport.data[i];
512
            item.setVisible(0);
513
        }
514
    },
515
    loadNavaid : func (type) {
516
        me._cache[type].index = 0;
517
        if (me._mapOptions.declutterNAV >= 3) { # TODO test for DME and NDB range < 100nm
518
            var range = me._mapOptions.range * 2.5;
519
            var txRange = MAP_TXRANGE_VOR[me._mapOptions.range];
520
            var results = positioned.findWithinRange(range, type);
521
            var item = nil;
522
            foreach (var n; results) {
523
                if (n.range_nm < txRange)
524
                    break;
525

            
526
                if (me._cache[type].index >= me._cache[type].max )
527
                    break;
528

            
529
                if (size(me._cache[type].data) > me._cache[type].index) {
530
                    item = me._cache[type].data[me._cache[type].index];
531
                    item.setData(n, type);
532
                }
533
                else {
534
                    item = MapNavaidItem.new(me._cache[type].index, type);
535
                    item.create(me._can[type]);
536
                    item.setData(n, type);
537
                    append(me._cache[type].data, item);
538
                }
539
                item.setVisible(1);
540
                me._cache[type].index += 1;
541
            }
542
        }
543
        for (var i = me._cache[type].index ; i < size(me._cache[type].data) ; i +=1) {
544
            item = me._cache[type].data[i];
545
            item.setVisible(0);
commit initial
Sébastien MARQUE authored on 2017-03-07
546
        }
adds Map on MFD
Sébastien MARQUE authored on 2017-03-20
547
    },
548
};
implements the ND from Extra...
Sébastien MARQUE authored on 2017-04-17
549
# }}}