Skip to content

Commit

Permalink
Add map annotation feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
lovettchris committed Mar 23, 2018
1 parent 931ffd4 commit 6ff1fd5
Show file tree
Hide file tree
Showing 7 changed files with 281 additions and 43 deletions.
12 changes: 11 additions & 1 deletion LogViewer/LogViewer/Controls/Console.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,17 @@ public void Write(string text)

if ((string)run.Tag == "user")
{
run = run.PreviousInline as Run;
var previousrun = run.PreviousInline as Run;
if (previousrun == null)
{
var newrun = new Run() { Foreground = ConsoleTextBrush };
last.Inlines.InsertBefore(run, newrun);
run = newrun;
}
else
{
run = previousrun;
}
}

// todo: process binary console commands embedded in the text...
Expand Down
2 changes: 1 addition & 1 deletion LogViewer/LogViewer/LogViewer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<SuiteName>PX4 Log Viewer</SuiteName>
<CreateWebPageOnPublish>true</CreateWebPageOnPublish>
<WebPage>publish.htm</WebPage>
<ApplicationRevision>44</ApplicationRevision>
<ApplicationRevision>45</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
Expand Down
14 changes: 10 additions & 4 deletions LogViewer/LogViewer/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
<Button x:Name="RecordButton" Style="{StaticResource AppBarButtonStyle}" Grid.Column="8" Click="OnRecord">&#xE102;</Button>

<Button x:Name="SettingsButton" Style="{StaticResource AppBarButtonStyle}" Grid.Column="9" Click="OnSettings">&#xE115;</Button>

<local:ConnectorControl x:Name="ConnectorControl" Grid.Column="11" Padding="0,15,0,0" Width="48" Height="48" ToolTip="Connection" MouseLeftButtonDown="OnConnectorClick" />
</Grid>

Expand All @@ -122,7 +122,13 @@
ItemContainerStyle="{StaticResource ContainerListItemStyle}"
Style="{StaticResource NavigationList}"
local:PassthroughMouseWheelBehavior.PassthroughMouseWheel="True"
PreviewMouseRightButtonDown="OnRightClickCategoryList"
ScrollViewer.CanContentScroll="False">
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Annotate on map" Click="OnAnnotateItem"/>
</ContextMenu>
</ListView.ContextMenu>
</ListView>
</local:ScrollViewerLite>

Expand All @@ -144,11 +150,11 @@
<Grid x:Name="CameraPanel" Background="Black" Grid.Row="2" Grid.Column="1" Visibility="Collapsed">
<Image x:Name="ImageViewer" />
</Grid>

<local:ChartStack x:Name="ChartStack" Focusable="True" Grid.Row="2" Grid.Column="1" Style="{StaticResource AppWorkspaceStack}" Background="Transparent">
</local:ChartStack>


<local:Console Grid.Row="2" Grid.Column="1" x:Name="SystemConsole"/>

<ProgressBar x:Name="MyProgress" Height="8" Grid.ColumnSpan="2" Grid.Row="3"/>
Expand All @@ -164,5 +170,5 @@
<TextBlock x:Name="StatusText" Text="" Margin="5" />
</Border>
</Grid>

</Window>
230 changes: 209 additions & 21 deletions LogViewer/LogViewer/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public partial class MainWindow : Window
MapPolyline currentFlight;
MavlinkLog currentFlightLog;
long lastAttitudeMessage;
List<LogEntry> mappedLogEntries;
MapLayer annotationLayer;

public MainWindow()
{
Expand Down Expand Up @@ -829,6 +831,7 @@ void ShowMap()
line.StrokeThickness = 4;
line.Stroke = new SolidColorBrush(GetRandomColor());
LocationCollection points = new LocationCollection();
mappedLogEntries = new List<Model.LogEntry>();

//Debug.WriteLine("time,\t\tlat,\t\tlong,\t\t\tnsat,\talt,\thdop,\tfix");
foreach (var row in log.GetRows("GPS", flight.StartTime, flight.Duration))
Expand All @@ -844,6 +847,7 @@ void ShowMap()
alt = 0;
}
mapData.Add(gps);
mappedLogEntries.Add(row);
var pos = new Location() { Altitude = alt, Latitude = gps.Lat, Longitude = gps.Lon };
points.Add(pos);
ulong time = (ulong)gps.GPSTime;
Expand Down Expand Up @@ -953,8 +957,6 @@ private void OnChildListItemSelected(object sender, SelectionChangedEventArgs e)

IEnumerable<DataValue> GetSelectedDataValues(LogItemSchema schema)
{
List<DataValue> combined = new List<DataValue>();

List<Flight> selected = GetSelectedFlights();
if (selected.Count == 0)
{
Expand All @@ -970,13 +972,14 @@ IEnumerable<DataValue> GetSelectedDataValues(LogItemSchema schema)
{
if (flight.Log == null || flight.Log == log)
{
combined.AddRange(log.GetDataValues(schema, flight.StartTime, flight.Duration));
foreach (var dv in log.GetDataValues(schema, flight.StartTime, flight.Duration))
{
yield return dv;
}
}
}
}
}

return combined;
}
}

Thickness defaultChartMargin = new Thickness(0, 10, 0, 10);
Expand Down Expand Up @@ -1100,22 +1103,184 @@ private void GraphItem(LogItemSchema schema)
else
{
StringBuilder sb = new StringBuilder();
string previous = null;
List<DataValue> unique = new List<Model.DataValue>();
foreach (var value in GetSelectedDataValues(schema))
{
if (!string.IsNullOrEmpty(value.Label))
{
sb.AppendLine(value.Label);
if (previous != value.Label)
{
unique.Add(value);
sb.Append(((ulong)value.X).ToString());
sb.Append(": ");
sb.AppendLine(value.Label);
previous = value.Label;
}
}
}
SystemConsole.Write(sb.ToString());
ConsoleButton.IsChecked = true;
SystemConsole.Show();
}
}

private void AnnotateMap(LogItemSchema schema)
{
List<DataValue> unique = new List<Model.DataValue>();
if (schema.IsNumeric)
{
var data = GetSelectedDataValues(schema);
ShowStatus(string.Format("Found {0} data values", data.Count()));
if (data.Count() > 0)
{
double previous = 0;
{
// uniquify it.
foreach (var value in data)
{
if (value.Y != previous)
{
unique.Add(value);
previous = value.Y;
}
}
}
}
}
else
{
StringBuilder sb = new StringBuilder();
string previous = null;
foreach (var value in GetSelectedDataValues(schema))
{
if (!string.IsNullOrEmpty(value.Label))
{
if (previous != value.Label)
{
unique.Add(value);
sb.Append(value.X.ToString());
sb.Append(": ");
sb.AppendLine(value.Label);
previous = value.Label;
}
}
}
}

// if there are too many values, then limit it to an even spread of 100 items.
if (unique.Count > 100)
{
var summary = new List<Model.DataValue>();
double skip = (unique.Count / 100);
for (int i = 0, n = unique.Count; i < n; i++)
{
var value = unique[i];
if (i >= summary.Count * unique.Count / 100)
{
summary.Add(value);
}
}
unique = summary;
}
AnnotateMap(unique);
}

private void AnnotateMap(List<DataValue> unique)
{
if (this.mappedLogEntries == null || this.mappedLogEntries.Count == 0)
{
ShowMap();
}

if (this.mappedLogEntries == null || this.mappedLogEntries.Count == 0)
{
MessageBox.Show("Sorry, could not find GPS map info, so cannot annotate data on the map",
"GPS info is missing", MessageBoxButton.OK, MessageBoxImage.Exclamation);
return;
}

if (annotationLayer != null)
{
myMap.Children.Remove(annotationLayer);
}
annotationLayer = new MapLayer();

SolidColorBrush annotationBrush = new SolidColorBrush(Color.FromArgb(0x80, 0xff, 0xff, 0xB0));

foreach (var dv in unique)
{
LogEntry closest = null;
LogField field = dv.UserData as LogField;
if (field != null)
{
// csv log
LogEntry e = field.Parent;
closest = FindNearestMappedItem(e.Timestamp);
}
else
{
// px4 log?
Message msg = dv.UserData as Message;
if (msg != null)
{
closest = FindNearestMappedItem(msg.GetTimestamp());
}
else
{
sb.AppendLine(value.Y.ToString());
// mavlink
MavlinkLog.Message mavmsg = dv.UserData as MavlinkLog.Message;
if (mavmsg != null)
{
closest = FindNearestMappedItem(mavmsg.Timestamp.Ticks / 10);
}
}
}

SystemConsole.Write(sb.ToString());
ConsoleButton.IsChecked = true;
SystemConsole.Show();
if (closest != null)
{
LogEntryGPS gps = new LogEntryGPS(closest);
// map doesn't like negative altitudes.
double alt = gps.Alt;
if (alt < 0)
{
alt = 0;
}
var pos = new Location() { Altitude = alt, Latitude = gps.Lat, Longitude = gps.Lon };
string label = dv.Label;
if (string.IsNullOrEmpty(label))
{
label = dv.Y.ToString();
}
annotationLayer.AddChild(new TextBlock(new Run(label) { Background = annotationBrush }), pos, PositionOrigin.BottomLeft);
}

}
myMap.Children.Add(annotationLayer);

SystemConsole.Hide();
ChartStack.Visibility = Visibility.Collapsed;
myMap.Visibility = Visibility.Visible;
myMap.UpdateLayout();
}

private LogEntry FindNearestMappedItem(double t)
{
LogEntry closest = null;
double bestDiff = 0;
// find nearest mapped location (nearest in time).
foreach (var mapped in this.mappedLogEntries)
{
var time = mapped.Timestamp;
var diff = Math.Abs((double)time - t);

if (closest == null || diff < bestDiff)
{
closest = mapped;
bestDiff = diff;
}
}
return closest;
}

private void OnNewChartGenerated(object sender, List<DataValue> e)
Expand Down Expand Up @@ -1178,6 +1343,10 @@ private void LayoutCharts()
double height = ChartStack.ActualHeight;
double count = ChartStack.ChartCount;
height -= (count * (defaultChartMargin.Top + defaultChartMargin.Bottom)); // remove margins
if (height < 0)
{
height = 0;
}
double chartHeight = Math.Min(MaxChartHeight, height / count);
bool found = false;
foreach (FrameworkElement c in ChartStack.Charts)
Expand Down Expand Up @@ -1250,6 +1419,7 @@ private void UnselectCategory(LogItemSchema item)
}
}


private void OnClear(object sender, RoutedEventArgs e)
{
ChartStack.ClearCharts();
Expand Down Expand Up @@ -1294,15 +1464,7 @@ private void OnFlightSelected(object sender, SelectionChangedEventArgs e)
}
});
}

//private void OnMapPointerMoved(object sender, PointerRoutedEventArgs e)
//{
// Point mapPos = e.GetCurrentPoint(myMap).Position;
// Geopoint location;
// myMap.GetLocationFromOffset(mapPos, out location);
// StatusText.Text = location.Position.Latitude + ", " + location.Position.Longitude;
//}


private void OnFlightViewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Delete)
Expand Down Expand Up @@ -1487,6 +1649,8 @@ struct IncomingImage

IncomingImage incoming_image = new IncomingImage();

public LogItemSchema rightClickedItem { get; private set; }

private void OnShowConsole(object sender, RoutedEventArgs e)
{
SystemConsole.Show();
Expand Down Expand Up @@ -1583,7 +1747,6 @@ private void DrawVectors(double[,] xmag, double[,] ymag)
// find guassian lines in the map and draw them so it looks like this:
// https://www.ngdc.noaa.gov/geomag/WMM/data/WMM2015/WMM2015_D_MERC.pdf


for (int i = 0; i < 180; i++)
{
for (int j = 0; j < 360; j++)
Expand Down Expand Up @@ -1619,6 +1782,31 @@ private void OnPaste(object sender, ExecutedRoutedEventArgs e)
CameraPanel.Visibility = Visibility.Visible;
}
}

private void OnAnnotateItem(object sender, RoutedEventArgs e)
{
LogItemSchema item = this.rightClickedItem;
if (item != null)
{
AnnotateMap(item);
}
}

private void OnRightClickCategoryList(object sender, MouseButtonEventArgs e)
{
this.rightClickedItem = null;
Point pos = e.GetPosition(CategoryList);
DependencyObject dep = (DependencyObject)e.OriginalSource;
while ((dep != null) && !(dep is ListViewItem))
{
dep = VisualTreeHelper.GetParent(dep);
}
if (dep == null)
return;
ListViewItem listitem = (ListViewItem)dep;
LogItemSchema item = listitem.DataContext as LogItemSchema;
this.rightClickedItem = item;
}
}
}

Loading

0 comments on commit 6ff1fd5

Please sign in to comment.