Skip to content

Commit 4819ab1

Browse files
committed
added multicolor flight trail
fixed resizing
1 parent 95b5b22 commit 4819ab1

File tree

8 files changed

+170
-86
lines changed

8 files changed

+170
-86
lines changed

css/main.css

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -500,17 +500,6 @@ html.has-log .log-graph-config {
500500
display:none;
501501
}
502502

503-
/* FIXME this should not be necessary when resizing is implemented */
504-
#mapContainer {
505-
z-index: 100;
506-
bottom:0 !important;
507-
display:none;
508-
height: 300px;
509-
width: 500px;
510-
}
511-
512-
513-
514503
html.has-craft #craftCanvas,
515504
html.has-analyser #analyserCanvas,
516505
html.has-map #mapContainer,
@@ -1234,6 +1223,11 @@ html:not(.has-log) #status-bar {
12341223
display: none;
12351224
}
12361225

1226+
html:not(.has-gps) .view-map,
1227+
html:not(.has-gps) .map-container {
1228+
display: none !important;
1229+
}
1230+
12371231
#status-bar .bookmark-1,
12381232
#status-bar .bookmark-2,
12391233
#status-bar .bookmark-3,

index.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<script src="js/vendor/modernizr-2.6.2-respond-1.1.0.min.js"></script>
2222
<script src="node_modules/leaflet/dist/leaflet.js"></script>
2323
<script src="node_modules/leaflet-marker-rotation/src/rotatedMarker.js" type="module"></script>
24+
<script src="node_modules/Leaflet.MultiOptionsPolyline/Leaflet.MultiOptionsPolyline.js"></script>
2425

2526
</head>
2627

@@ -2911,6 +2912,15 @@ <h4 class="modal-title">Advanced User Settings</h4>
29112912
<div class="spacer_box_title">Map Settings</div>
29122913
</div>
29132914
<div class="spacer_box">
2915+
<div>
2916+
<label class="option">ACT
2917+
<input class="map-trail-altitude-colored ios-switch" type="checkbox" />
2918+
<div>
2919+
<div></div>
2920+
</div>
2921+
<span>Use Altitude Colored Trail (slower at loading/changing logs)</span>
2922+
</label>
2923+
</div>
29142924
<table>
29152925
<tr>
29162926
<td>

js/flightlog.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,6 +1059,10 @@ function FlightLog(logData) {
10591059

10601060
return true;
10611061
};
1062+
1063+
this.hasGpsData = function() {
1064+
return this.getStats()?.frame?.G ? true : false;;
1065+
};
10621066
}
10631067

10641068
FlightLog.prototype.accRawToGs = function(value) {

js/graph_map.js

Lines changed: 125 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ function MapGrapher() {
1515
previousLogIndex,
1616
latIndexAtFrame,
1717
lngIndexAtFrame,
18+
altitudeIndexAtFrame,
1819
groundCourseIndexAtFrame,
1920
flightLog;
2021

2122
const coordinateDivider = 10000000;
23+
const altitudeDivider = 10;
2224
const grounCourseDivider = 10;
2325

2426
const mapOptions = {
@@ -46,7 +48,19 @@ function MapGrapher() {
4648
smoothFactor: 1,
4749
};
4850

49-
// debug circles can be used to aligh icons with the correct coordinates
51+
// flight trail colors
52+
const colorTrailGradient = [
53+
{ color: "#00ffe0bf" },
54+
{ color: "#00ff8cbf" },
55+
{ color: "#00ff02bf" },
56+
{ color: "#75ff00bf" },
57+
{ color: "#e5ff00bf" },
58+
{ color: "#ffb100bf" },
59+
{ color: "#ff4c00bf" },
60+
{ color: "#ff1414" },
61+
];
62+
63+
// debug circles can be used to aligh icons at the correct coordinates
5064
const debugCircle = false;
5165
const debugCircleOptions = {
5266
color: "red",
@@ -55,9 +69,8 @@ function MapGrapher() {
5569
radius: 1,
5670
};
5771

58-
this.init = function (options) {
72+
this.initialize = function () {
5973
if (myMap) return;
60-
userSettings = options;
6174

6275
myMap = L.map("mapContainer", mapOptions);
6376

@@ -67,18 +80,25 @@ function MapGrapher() {
6780
attribution:
6881
'&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
6982
}).addTo(myMap);
70-
71-
this.setFlightType();
7283
};
7384

7485
this.reset = function () {
75-
console.log("reset");
76-
// this.clearMap(0);
77-
// trailLayers = new Map();
78-
// previousLogIndex = null;
79-
// myMap.setView([0, 0], 1);
80-
81-
// reset points map
86+
if (!myMap) return;
87+
this.clearMap(previousLogIndex);
88+
previousLogIndex = null;
89+
currentTime = null;
90+
craftPosition = null;
91+
groundCourse = null;
92+
homePosition = null;
93+
craftMarker = null;
94+
homeMarker = null;
95+
trailLayers = new Map();
96+
previousLogIndex = null;
97+
latIndexAtFrame = null;
98+
lngIndexAtFrame = null;
99+
altitudeIndexAtFrame = null;
100+
groundCourseIndexAtFrame = null;
101+
myMap.setView(mapOptions.center, mapOptions.zoom);
82102
};
83103

84104
this.setFlightLog = function (newFlightLog) {
@@ -90,14 +110,9 @@ function MapGrapher() {
90110
currentLogStartDateTime = newLogStartDateTime;
91111
}
92112

93-
// time was intended to mark the trail with a different color when IN/OUT is set.
94-
// the problem is that simplification of the curve should be done in 2/3 parts depending on IN/OUT
95-
// if IN is set: from startTime to IN - from IN to endTime (2 parts)
96-
// if OUT is set: from startTime to OUT - from OUT to endTime (2 parts)
97-
// if BOTH are set: from startTime to IN - from IN to OUT - from OUT to endTime (3 parts)
98-
// const time = flightLog.getMainFieldIndexByName("time");
99113
latIndexAtFrame = flightLog.getMainFieldIndexByName("GPS_coord[0]");
100114
lngIndexAtFrame = flightLog.getMainFieldIndexByName("GPS_coord[1]");
115+
altitudeIndexAtFrame = flightLog.getMainFieldIndexByName("GPS_altitude");
101116
groundCourseIndexAtFrame =
102117
flightLog.getMainFieldIndexByName("GPS_ground_course");
103118

@@ -107,35 +122,75 @@ function MapGrapher() {
107122
flightLog.getMinTime(),
108123
flightLog.getMaxTime()
109124
);
110-
const chunksLength = chunks.length;
111125

112126
let latlngs = [];
113127

114128
// if this log is already proccesed its skipped
115129
if (trailLayers.has(logIndex)) return;
116130

117-
for (let ci = 0; ci < chunksLength; ci++) {
118-
const chunk = chunks[ci];
119-
const frames = chunk.frames;
120-
121-
for (let fi = 0; fi < frames.length; fi++) {
122-
const frame = frames[fi];
131+
let maxAlt = Number.MIN_VALUE;
132+
let minAlt = Number.MAX_VALUE;
123133

134+
for (const chunk of chunks) {
135+
for (const fi in chunk.frames) {
136+
const frame = chunk.frames[fi];
124137
const coordinates = this.getCoordinatesFromFrame(
125138
frame,
126139
latIndexAtFrame,
127-
lngIndexAtFrame
140+
lngIndexAtFrame,
141+
altitudeIndexAtFrame
128142
);
129143

130-
// if we have no values we skip the frame
144+
// if there are no coordinates the frame is skipped
131145
if (!coordinates) continue;
132-
latlngs.push(coordinates);
146+
147+
maxAlt = coordinates.alt > maxAlt ? coordinates.alt : maxAlt;
148+
minAlt = coordinates.alt < minAlt ? coordinates.alt : minAlt;
149+
150+
// 1/4 of the dots is enough to draw the line
151+
if (fi % 4 == 0) latlngs.push(coordinates);
133152
}
134153
}
135154

136155
const polyline = L.polyline(latlngs, polylineOptions);
137156

138-
trailLayers.set(logIndex, polyline);
157+
const divider = colorTrailGradient.length - 1;
158+
159+
// FIXME altitude max and min values can be obtained from the stats but fixing the index at 4 doesn't seem safe
160+
// const maxAlt2 = flightLog.getStats().frame.G.field[4].max / altitudeDivider; //197
161+
// const minAlt2 = flightLog.getStats().frame.G.field[4].min / altitudeDivider; //54
162+
163+
const delta = maxAlt - minAlt;
164+
165+
const thresholdIncrement = delta / divider;
166+
167+
let altThresholds = [];
168+
let threshold = minAlt;
169+
for (let i = 0; i < divider; i++) {
170+
//amount of colors - min and max that are set
171+
threshold += thresholdIncrement;
172+
altThresholds.push(threshold);
173+
}
174+
175+
const polylineC = L.multiOptionsPolyline(latlngs, {
176+
multiOptions: {
177+
optionIdxFn: function (latLng) {
178+
for (const i in altThresholds) {
179+
if (latLng.alt <= altThresholds[i]) {
180+
return i;
181+
}
182+
}
183+
return altThresholds.length;
184+
},
185+
options: colorTrailGradient,
186+
},
187+
weight: 3,
188+
lineCap: "butt",
189+
opacity: 1,
190+
smoothFactor: 1,
191+
});
192+
193+
trailLayers.set(logIndex, { polyline, polylineC });
139194

140195
if (latlngs.length > 0)
141196
homePosition = this.getHomeCoordinatesFromFlightLog(flightLog);
@@ -147,7 +202,8 @@ function MapGrapher() {
147202
craftPosition = this.getCoordinatesFromFrame(
148203
frame.current,
149204
latIndexAtFrame,
150-
lngIndexAtFrame
205+
lngIndexAtFrame,
206+
altitudeIndexAtFrame
151207
);
152208
groundCourse = this.getGroundCourseFromFrame(
153209
frame.current,
@@ -156,6 +212,10 @@ function MapGrapher() {
156212
} catch (e) {}
157213
};
158214

215+
this.setUserSettings = function (newUserSettings) {
216+
userSettings = newUserSettings;
217+
};
218+
159219
this.redraw = function () {
160220
if (trailLayers.size <= 0) return;
161221
if (!myMap) return;
@@ -165,7 +225,9 @@ function MapGrapher() {
165225
if (previousLogIndex != currentLogIndex) {
166226
this.clearMap(previousLogIndex);
167227
if (trailLayers.has(currentLogIndex)) {
168-
const polyline = trailLayers.get(currentLogIndex);
228+
const polyline = userSettings.mapTrailAltitudeColored
229+
? trailLayers.get(currentLogIndex).polylineC
230+
: trailLayers.get(currentLogIndex).polyline;
169231
polyline.addTo(myMap);
170232
myMap.fitBounds(polyline.getBounds());
171233
}
@@ -182,7 +244,6 @@ function MapGrapher() {
182244
if (debugCircle) homeMarker.circle.setLatLng(homePosition).addTo(myMap);
183245
} else {
184246
homeMarker = {};
185-
console.log("homePosition", homePosition);
186247

187248
homeMarker.icon = L.marker(homePosition, {
188249
icon: homeIcon,
@@ -196,7 +257,7 @@ function MapGrapher() {
196257
}
197258
}
198259

199-
// //aircraft
260+
// aircraft
200261
if (craftPosition) {
201262
if (craftMarker) {
202263
craftMarker.icon.setLatLng(craftPosition);
@@ -224,47 +285,50 @@ function MapGrapher() {
224285

225286
this.clearMap = function (index) {
226287
if (trailLayers.has(index)) {
227-
myMap.removeLayer(trailLayers.get(index));
288+
const p = trailLayers.get(index).polyline;
289+
const pc = trailLayers.get(index).polylineC;
290+
if (p) myMap.removeLayer(p);
291+
if (pc) myMap.removeLayer(pc);
228292
}
229293
if (homeMarker) {
230-
myMap.removeLayer(homeMarker.icon);
231-
myMap.removeLayer(homeMarker.circle);
294+
if (myMap.hasLayer(homeMarker.icon)) myMap.removeLayer(homeMarker.icon);
295+
if (debugCircle && myMap.hasLayer(homeMarker.circle))
296+
myMap.removeLayer(homeMarker.circle);
232297
}
233298
if (craftMarker) {
234-
myMap.removeLayer(craftMarker.icon);
235-
myMap.removeLayer(craftMarker.circle);
299+
if (myMap.hasLayer(craftMarker.icon)) myMap.removeLayer(craftMarker.icon);
300+
if (debugCircle && myMap.hasLayer(craftMarker.circle))
301+
myMap.removeLayer(craftMarker.circle);
236302
}
237303
};
238304

239305
this.resize = function (width, height) {
240-
console.log("this.resize");
241-
// if (!userSettings) return;
242-
243-
// const containerstyle = {
244-
// // height: height * parseInt(userSettings.map.size) / 100.0,
245-
// // width: height * parseInt(userSettings.map.size) / 100.0,
246-
// left: (width * parseInt(userSettings.map.left)) / 100.0,
247-
// top: (height * parseInt(userSettings.map.top)) / 100.0,
248-
// };
249-
250-
// const canvasstyle = {
251-
// height: (height * parseInt(userSettings.map.size)) / 100.0,
252-
// width: (width * parseInt(userSettings.map.size)) / 100.0,
253-
// // left: (height * parseInt(userSettings.map.left) / 100.0),
254-
// // top: (height * parseInt(userSettings.map.top) / 100.0)
255-
// };
256-
257-
// $("#mapContainer").css(containerstyle);
258-
// $("#mapContainer .leaflet-container").css(canvasstyle);
259-
260-
// redraw();
306+
if (!userSettings) return;
307+
const containerstyle = {
308+
height: (height * parseInt(userSettings.map.size)) / 100.0,
309+
width: (width * parseInt(userSettings.map.size)) / 100.0,
310+
left: (width * parseInt(userSettings.map.left)) / 100.0,
311+
top: (height * parseInt(userSettings.map.top)) / 100.0,
312+
};
313+
$("#mapContainer").css(containerstyle);
261314
};
262315

263-
this.getCoordinatesFromFrame = function (frame, latIndex, lngIndex) {
316+
this.getCoordinatesFromFrame = function (
317+
frame,
318+
latIndex,
319+
lngIndex,
320+
altitudeIndex
321+
) {
264322
const lat = frame[latIndex];
265323
const lng = frame[lngIndex];
324+
const alt = frame[altitudeIndex];
325+
266326
return typeof lat == "number" || typeof lng == "number"
267-
? [lat / coordinateDivider, lng / coordinateDivider]
327+
? L.latLng(
328+
lat / coordinateDivider,
329+
lng / coordinateDivider,
330+
alt / altitudeDivider
331+
)
268332
: null;
269333
};
270334

@@ -278,13 +342,6 @@ function MapGrapher() {
278342
return [home[0].min / coordinateDivider, home[1].min / coordinateDivider];
279343
};
280344

281-
this.setFlightType = function () {
282-
if ($("html").hasClass("isBF")) flightType = "isBF";
283-
else if ($("html").hasClass("isCF")) flightType = "isCF";
284-
else if ($("html").hasClass("isINAV")) flightType = "isINAV";
285-
else flightType = "isBF";
286-
};
287-
288345
this.setCurrentTime = function (newTime) {
289346
currentTime = newTime;
290347
this.updateCurrentPosition();

0 commit comments

Comments
 (0)