add map support for gps denied

This commit is contained in:
Alex Bezdieniezhnykh
2025-03-17 09:08:43 +02:00
parent 33070b90bf
commit 099f9cf52b
15 changed files with 783 additions and 21 deletions
+52 -11
View File
@@ -3,7 +3,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpf="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF" xmlns:controls="clr-namespace:Azaion.Annotator.Controls"
xmlns:wpf="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"
xmlns:controls="clr-namespace:Azaion.Annotator.Controls"
xmlns:controls1="clr-namespace:Azaion.Common.Controls;assembly=Azaion.Common"
xmlns:controls2="clr-namespace:Azaion.Annotator.Controls;assembly=Azaion.Common"
mc:Ignorable="d"
@@ -54,9 +55,11 @@
ShowGridLines="False"
Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="28"></RowDefinition>
<RowDefinition Height="32"></RowDefinition>
<RowDefinition Height="*" Name="DetectionSection" />
<RowDefinition Height="0" Name="GpsSplitterRow" />
<RowDefinition Height="0" Name="GpsSectionRow"/>
<RowDefinition Height="28" Name="ProgressBarSection"/>
<RowDefinition Height="32" Name="ButtonsSection"></RowDefinition>
</Grid.RowDefinitions>
<Grid
@@ -280,9 +283,25 @@
</DataGrid>
</Grid>
<GridSplitter
Name="GpsSplitter"
Background="DarkGray"
ResizeDirection="Rows"
Grid.Row="1"
ResizeBehavior="PreviousAndNext"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Visibility="Collapsed" />
<controls:MapMatcher
x:Name="MapMatcherComponent"
Grid.Column="0"
Grid.Row="2"
/>
<controls2:UpdatableProgressBar x:Name="VideoSlider"
Grid.Column="0"
Grid.Row="1"
Grid.Row="3"
Background="#252525"
Foreground="LightBlue">
</controls2:UpdatableProgressBar>
@@ -290,7 +309,7 @@
<!-- Buttons -->
<Grid
Name="Buttons"
Grid.Row="2"
Grid.Row="4"
Background="Black"
>
<Grid.ColumnDefinitions>
@@ -306,7 +325,9 @@
<ColumnDefinition Width="56" /> <!-- 9 -->
<ColumnDefinition Width="28" /> <!-- 10 -->
<ColumnDefinition Width="28" /> <!-- 11 -->
<ColumnDefinition Width="*" /> <!-- 12-->
<ColumnDefinition Width="28" /> <!-- 12 -->
<ColumnDefinition Width="0" /> <!-- 13 -->
<ColumnDefinition Width="*" /> <!-- 14-->
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Padding="5" ToolTip="Включити програвання" Background="Black" BorderBrush="Black"
Click="PlayClick">
@@ -484,7 +505,6 @@
Maximum="100" Minimum="0">
</controls2:UpdatableProgressBar>
<Button
x:Name="AIDetectBtn"
Grid.Column="10"
@@ -518,7 +538,29 @@
21.333 5.494 5.493 13.058 8.907 21.343 8.907h223.368c8.273 0 15.833-3.421 21.326-8.914s8.915-13.053
8.915-21.326V141.338c0-8.283-3.414-15.848-8.908-21.341v-.049c-5.454-5.456-13.006-8.851-21.333-8.851z" />
</Button>
<Button Grid.Column="11"
<Button Grid.Column="11" Padding="2" Width="25" Height="25" ToolTip="Показати GPS. Клавіша: [M]" Background="Black" BorderBrush="Black"
Click="SwitchGpsPanel">
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V520 H580 V0 H0 Z">
<GeometryDrawing Brush="LightGray" Geometry="M307.1,311.97c-12.55-14-22.75-31.86-32.9-47.68c-10.23-15.94-19.78-32.43-27.3-49.83c-7.03-16.28-12.48-33.08-9.25-50.97
c2.87-15.93,11.75-31.29,23.84-42.03c22.3-19.8,57.81-22.55,82.67-5.98c29.17,19.45,39.48,55.06,27.59,87.55
c-6.8,18.59-16.41,36.14-27.02,52.8C332.76,274.63,320.84,294.45,307.1,311.97z M307.01,143.45c-38.65-0.46-39.68,59.79-0.95,60.47
c16.47,0.29,30.83-13.34,31-29.9C337.22,157.75,323.24,143.65,307.01,143.45z" />
<GeometryDrawing Brush="LightGray" Geometry="M367.34,310.68c10.09,2.5,23.61,4.83,31.46,12.19c11.05,10.35-5.42,18.17-14.21,21.43c-24.55,9.11-53.52,10.41-79.44,10.11
c-25.7-0.3-54.62-1.23-78.68-11.19c-7.68-3.18-21.53-10.2-12.52-19.47c8.26-8.49,23.33-11.42,34.5-12.94
c-5.15,1.98-16.18,5.12-17.07,11.49c-1,7.13,9.78,10.81,15.02,12.59c18.28,6.22,38.72,7.58,57.89,7.73
c18.91,0.15,38.85-0.72,57.13-5.92c5.72-1.63,18.65-4.74,20.7-11.49c2.28-7.47-9.8-11.66-15.04-13.71
C367.18,311.22,367.26,310.95,367.34,310.68z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
<Button Grid.Column="12"
Padding="2"
Width="25"
Height="25"
@@ -571,8 +613,7 @@
</Image.Source>
</Image>
</Button>
<StatusBar Grid.Column="12"
<StatusBar Grid.Column="14"
Background="#252525"
Foreground="White">
<StatusBar.ItemsPanel>
+24
View File
@@ -43,6 +43,7 @@ public partial class Annotator
private ObservableCollection<DetectionClass> AnnotationClasses { get; set; } = new();
private bool _suspendLayout;
private bool _gpsPanelVisible = false;
public readonly CancellationTokenSource MainCancellationSource = new();
public CancellationTokenSource DetectionCancellationSource = new();
@@ -105,6 +106,7 @@ public partial class Annotator
};
Editor.GetTimeFunc = () => TimeSpan.FromMilliseconds(_mediaPlayer.Time);
MapMatcherComponent.Init(_appConfig);
}
private void OnLoaded(object sender, RoutedEventArgs e)
@@ -587,6 +589,28 @@ public partial class Annotator
});
}
private void SwitchGpsPanel(object sender, RoutedEventArgs e)
{
_gpsPanelVisible = !_gpsPanelVisible;
if (_gpsPanelVisible)
{
GpsSplitterRow.Height = new GridLength(4);
GpsSplitter.Visibility = Visibility.Visible;
GpsSectionRow.Height = new GridLength(1, GridUnitType.Star);
MapMatcherComponent.Visibility = Visibility.Visible;
}
else
{
GpsSplitterRow.Height = new GridLength(0);
GpsSplitter.Visibility = Visibility.Collapsed;
GpsSectionRow.Height = new GridLength(0);
MapMatcherComponent.Visibility = Visibility.Collapsed;
}
}
private void SoundDetections(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
+1
View File
@@ -8,6 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GMap.NET.WinPresentation" Version="2.1.7" />
<PackageReference Include="libc.translation" Version="7.1.1" />
<PackageReference Include="LibVLCSharp" Version="3.9.1" />
<PackageReference Include="LibVLCSharp.WPF" Version="3.9.1" />
+348
View File
@@ -0,0 +1,348 @@
using System.Globalization;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using GMap.NET.WindowsPresentation;
namespace Azaion.Annotator.Controls
{
public class CircleVisual : FrameworkElement
{
public readonly GMapMarker Marker;
public CircleVisual(GMapMarker m, Brush background)
{
Marker = m;
Marker.ZIndex = 100;
SizeChanged += CircleVisual_SizeChanged;
MouseEnter += CircleVisual_MouseEnter;
MouseLeave += CircleVisual_MouseLeave;
Loaded += OnLoaded;
Text = "?";
StrokeArrow.EndLineCap = PenLineCap.Triangle;
StrokeArrow.LineJoin = PenLineJoin.Round;
RenderTransform = _scale;
Width = Height = 22;
FontSize = Width / 1.55;
Background = background;
Angle = null;
}
void CircleVisual_SizeChanged(object sender, SizeChangedEventArgs e)
{
Marker.Offset = new Point(-e.NewSize.Width / 2, -e.NewSize.Height / 2);
_scale.CenterX = -Marker.Offset.X;
_scale.CenterY = -Marker.Offset.Y;
}
void OnLoaded(object sender, RoutedEventArgs e)
{
UpdateVisual(true);
}
readonly ScaleTransform _scale = new ScaleTransform(1, 1);
void CircleVisual_MouseLeave(object sender, MouseEventArgs e)
{
Marker.ZIndex -= 10000;
Cursor = Cursors.Arrow;
Effect = null;
_scale.ScaleY = 1;
_scale.ScaleX = 1;
}
void CircleVisual_MouseEnter(object sender, MouseEventArgs e)
{
Marker.ZIndex += 10000;
Cursor = Cursors.Hand;
Effect = ShadowEffect;
_scale.ScaleY = 1.5;
_scale.ScaleX = 1.5;
}
public DropShadowEffect ShadowEffect;
static readonly Typeface Font = new Typeface(new FontFamily("Arial"),
FontStyles.Normal,
FontWeights.Bold,
FontStretches.Normal);
FormattedText _fText;
private Brush _background = Brushes.Blue;
public Brush Background
{
get
{
return _background;
}
set
{
if (_background != value)
{
_background = value;
IsChanged = true;
}
}
}
private Brush _foreground = Brushes.White;
public Brush Foreground
{
get
{
return _foreground;
}
set
{
if (_foreground != value)
{
_foreground = value;
IsChanged = true;
ForceUpdateText();
}
}
}
private Pen _stroke = new Pen(Brushes.Blue, 2.0);
public Pen Stroke
{
get
{
return _stroke;
}
set
{
if (_stroke != value)
{
_stroke = value;
IsChanged = true;
}
}
}
private Pen _strokeArrow = new Pen(Brushes.Blue, 2.0);
public Pen StrokeArrow
{
get
{
return _strokeArrow;
}
set
{
if (_strokeArrow != value)
{
_strokeArrow = value;
IsChanged = true;
}
}
}
public double FontSize = 16;
private double? _angle = 0;
public double? Angle
{
get
{
return _angle;
}
set
{
if (!Angle.HasValue || !value.HasValue ||
Angle.HasValue && value.HasValue && Math.Abs(_angle.Value - value.Value) > 11)
{
_angle = value;
IsChanged = true;
}
}
}
public bool IsChanged = true;
void ForceUpdateText()
{
_fText = new FormattedText(_text,
CultureInfo.InvariantCulture,
FlowDirection.LeftToRight,
Font,
FontSize,
Foreground);
IsChanged = true;
}
string _text;
public string Text
{
get
{
return _text;
}
set
{
if (_text != value)
{
_text = value;
ForceUpdateText();
}
}
}
Visual _child;
public virtual Visual Child
{
get
{
return _child;
}
set
{
if (_child != value)
{
if (_child != null)
{
RemoveLogicalChild(_child);
RemoveVisualChild(_child);
}
if (value != null)
{
AddVisualChild(value);
AddLogicalChild(value);
}
// cache the new child
_child = value;
InvalidateVisual();
}
}
}
public bool UpdateVisual(bool forceUpdate)
{
if (forceUpdate || IsChanged)
{
Child = Create();
IsChanged = false;
return true;
}
return false;
}
int _countCreate;
private DrawingVisual Create()
{
_countCreate++;
var square = new DrawingVisualFx();
using (var dc = square.RenderOpen())
{
dc.DrawEllipse(null,
Stroke,
new Point(Width / 2, Height / 2),
Width / 2 + Stroke.Thickness / 2,
Height / 2 + Stroke.Thickness / 2);
if (Angle.HasValue)
{
dc.PushTransform(new RotateTransform(Angle.Value, Width / 2, Height / 2));
{
var polySeg = new PolyLineSegment(new[]
{
new Point(Width * 0.2, Height * 0.3), new Point(Width * 0.8, Height * 0.3)
},
true);
var pathFig = new PathFigure(new Point(Width * 0.5, -Height * 0.22),
new PathSegment[] {polySeg},
true);
var pathGeo = new PathGeometry(new[] {pathFig});
dc.DrawGeometry(Brushes.AliceBlue, StrokeArrow, pathGeo);
}
dc.Pop();
}
dc.DrawEllipse(Background, null, new Point(Width / 2, Height / 2), Width / 2, Height / 2);
dc.DrawText(_fText, new Point(Width / 2 - _fText.Width / 2, Height / 2 - _fText.Height / 2));
}
return square;
}
#region Necessary Overrides -- Needed by WPF to maintain bookkeeping of our hosted visuals
protected override int VisualChildrenCount
{
get
{
return Child == null ? 0 : 1;
}
}
protected override Visual GetVisualChild(int index)
{
return Child;
}
#endregion
}
public class DrawingVisualFx : DrawingVisual
{
public static readonly DependencyProperty EffectProperty = DependencyProperty.Register("Effect",
typeof(Effect),
typeof(DrawingVisualFx),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender,
OnEffectChanged));
public new Effect Effect
{
get
{
return (Effect)GetValue(EffectProperty);
}
set
{
SetValue(EffectProperty, value);
}
}
private static void OnEffectChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var drawingVisualFx = o as DrawingVisualFx;
if (drawingVisualFx != null)
{
drawingVisualFx.SetMyProtectedVisualEffect((Effect)e.NewValue);
}
}
private void SetMyProtectedVisualEffect(Effect effect)
{
VisualEffect = effect;
}
}
}
+118
View File
@@ -0,0 +1,118 @@
<UserControl x:Class="Azaion.Annotator.Controls.MapMatcher"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Azaion.Annotator.Controls"
xmlns:windowsPresentation="clr-namespace:GMap.NET.WindowsPresentation;assembly=GMap.NET.WindowsPresentation"
xmlns:controls="clr-namespace:Azaion.Common.Controls;assembly=Azaion.Common"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="1200">
<Grid
Name="MatcherGrid"
ShowGridLines="False"
Background="Black"
HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250" /> <!-- 0 list view -->
<ColumnDefinition Width="4"/> <!-- 1 splitter -->
<ColumnDefinition Width="*" /> <!-- 2 ExplorerEditor -->
<ColumnDefinition Width="4"/> <!-- 3 splitter -->
<ColumnDefinition Width="*" /> <!-- 4 Maps Control -->
</Grid.ColumnDefinitions>
<Grid
HorizontalAlignment="Stretch"
Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="28"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBox
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Stretch"
Margin="1"
x:Name="TbGpsMapFolder"></TextBox>
<Button
Grid.Row="0"
Grid.Column="1"
Margin="1"
Click="OpenGpsTilesFolderClick">
. . .
</Button>
<ListView Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
Name="GpsFiles"
Background="Black"
SelectedItem="{Binding Path=SelectedVideo}"
Foreground="#FFDDDDDD">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding HasAnnotations}" Value="true">
<Setter Property="Background" Value="#FF505050"/>
</DataTrigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value=" DimGray" />
<Setter Property="Background" Value="#FFCCCCCC"></Setter>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="DimGray"></Setter>
</Trigger>
</Style.Triggers>
<EventSetter Event="ContextMenuOpening" Handler="GpsFilesContextOpening"></EventSetter>
</Style>
</ListView.Resources>
<ListView.ContextMenu>
<ContextMenu Name="GpsFilesContextMenu">
<MenuItem Header="Відкрити папку..." Click="OpenContainingFolder" Background="WhiteSmoke" />
</ContextMenu>
</ListView.ContextMenu>
<ListView.View>
<GridView>
<GridViewColumn Width="Auto"
Header="Файл"
DisplayMemberBinding="{Binding Path=Name}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
<GridSplitter
Background="DarkGray"
ResizeDirection="Columns"
Grid.Column="1"
ResizeBehavior="PreviousAndNext"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
<controls:CanvasEditor
Grid.Column="2"
x:Name="GpsImageEditor"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" >
</controls:CanvasEditor>
<GridSplitter
Background="DarkGray"
ResizeDirection="Columns"
Grid.Column="3"
ResizeBehavior="PreviousAndNext"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
<windowsPresentation:GMapControl
Grid.Column="4"
x:Name="SatelliteMap"
Zoom="20" MaxZoom="24" MinZoom="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
MinWidth="400" />
</Grid>
</UserControl>
@@ -0,0 +1,152 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using Azaion.Common;
using Azaion.Common.Database;
using Azaion.Common.DTO;
using Azaion.Common.DTO.Config;
using Azaion.Common.Extensions;
using GMap.NET;
using GMap.NET.MapProviders;
using GMap.NET.WindowsPresentation;
using Microsoft.WindowsAPICodePack.Dialogs;
namespace Azaion.Annotator.Controls;
public partial class MapMatcher : UserControl
{
private AppConfig _appConfig;
List<MediaFileInfo> _allMediaFiles;
private Dictionary<string, Annotation> _annotations;
private string _currentDir;
public MapMatcher()
{
InitializeComponent();
}
public void Init(AppConfig appConfig)
{
_appConfig = appConfig;
GoogleMapProvider.Instance.ApiKey = appConfig.MapConfig.ApiKey;
SatelliteMap.MapProvider = GMapProviders.GoogleSatelliteMap;
SatelliteMap.Position = new PointLatLng(48.295985271707664, 37.14477539062501);
SatelliteMap.MultiTouchEnabled = true;
GpsFiles.MouseDoubleClick += async (sender, args) =>
{
var media = (GpsFiles.SelectedItem as MediaFileInfo)!;
var ann = _annotations.GetValueOrDefault(Path.GetFileNameWithoutExtension(media.Name));
GpsImageEditor.Background = new ImageBrush
{
ImageSource = await Path.Combine(_currentDir, ann.Name).OpenImage()
};
SatelliteMap.Position = new PointLatLng(ann.Lat, ann.Lon);
};
}
private void GpsFilesContextOpening(object sender, ContextMenuEventArgs e)
{
var listItem = sender as ListViewItem;
GpsFilesContextMenu.DataContext = listItem!.DataContext;
}
private void OpenContainingFolder(object sender, RoutedEventArgs e)
{
var mediaFileInfo = (sender as MenuItem)?.DataContext as MediaFileInfo;
if (mediaFileInfo == null)
return;
Process.Start("explorer.exe", "/select,\"" + mediaFileInfo.Path +"\"");
}
private async void OpenGpsTilesFolderClick(object sender, RoutedEventArgs e)
{
var dlg = new CommonOpenFileDialog
{
Title = "Open Video folder",
IsFolderPicker = true,
InitialDirectory = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)
};
var dialogResult = dlg.ShowDialog();
if (dialogResult != CommonFileDialogResult.Ok || string.IsNullOrEmpty(dlg.FileName))
return;
TbGpsMapFolder.Text = dlg.FileName;
_currentDir = dlg.FileName;
var dir = new DirectoryInfo(dlg.FileName);
var mediaFiles = dir.GetFiles(_appConfig.AnnotationConfig.ImageFormats.ToArray())
.Select(x => new MediaFileInfo
{
Name = x.Name,
Path = x.FullName,
MediaType = MediaTypes.Image
}).ToList();
// var allFiles = videoFiles.Concat(imageFiles).ToList();
//
// var labelsDict = await _dbFactory.Run(async db => await db.Annotations
// .GroupBy(x => x.Name.Substring(0, x.Name.Length - 7))
// .Where(x => allFileNames.Contains(x.Key))
// .ToDictionaryAsync(x => x.Key, x => x.Key));
//
// foreach (var mediaFile in allFiles)
// mediaFile.HasAnnotations = labelsDict.ContainsKey(mediaFile.FName);
//
// AllMediaFiles = new ObservableCollection<MediaFileInfo>(allFiles);
_allMediaFiles = mediaFiles;
GpsFiles.ItemsSource = new ObservableCollection<MediaFileInfo>(_allMediaFiles);
var annotations = SetFromCsv(mediaFiles);
await Task.Delay(TimeSpan.FromSeconds(10));
SetMarkers(annotations);
}
private Dictionary<string, Annotation> SetFromCsv(List<MediaFileInfo> mediaFiles)
{
_annotations = mediaFiles.Select(x => new Annotation
{
Name = x.Name,
OriginalMediaName = x.Name
}).ToDictionary(x => Path.GetFileNameWithoutExtension(x.OriginalMediaName));
var csvResults = GpsCsvResult.ReadFromCsv(Constants.CSV_PATH);
var csvDict = csvResults.ToDictionary(x => x.Image);
foreach (var ann in _annotations)
{
var csvRes = csvDict.GetValueOrDefault(ann.Key);
if (csvRes == null)
continue;
ann.Value.Lat = csvRes.Latitude;
ann.Value.Lon = csvRes.Longitude;
}
return _annotations;
}
private void SetMarkers(Dictionary<string, Annotation> annotations)
{
if (!annotations.Any())
return;
var firstAnnotation = annotations.FirstOrDefault();
SatelliteMap.Position = new PointLatLng(firstAnnotation.Value.Lat, firstAnnotation.Value.Lon);
foreach (var ann in annotations)
{
var marker = new GMapMarker(new PointLatLng(ann.Value.Lat, ann.Value.Lon));
var circle = new CircleVisual(marker, System.Windows.Media.Brushes.Blue)
{
Text = " "
};
marker.Shape = circle;
SatelliteMap.Markers.Add(marker);
}
}
}
+1
View File
@@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="33.0.1" />
<PackageReference Include="linq2db.SQLite" Version="5.4.1" />
<PackageReference Include="MediatR" Version="12.4.1" />
<PackageReference Include="MessagePack" Version="3.1.0" />
+1
View File
@@ -90,4 +90,5 @@ public class Constants
#endregion
public const string CSV_PATH = "D:\\matches.csv";
}
+18 -6
View File
@@ -8,17 +8,19 @@ namespace Azaion.Common.DTO.Config;
public class AppConfig
{
public PythonConfig PythonConfig { get; set; } = null!;
public PythonConfig PythonConfig { get; set; } = null!;
public QueueConfig QueueConfig { get; set; } = null!;
public QueueConfig QueueConfig { get; set; } = null!;
public DirectoriesConfig DirectoriesConfig { get; set; } = null!;
public DirectoriesConfig DirectoriesConfig { get; set; } = null!;
public AnnotationConfig AnnotationConfig { get; set; } = null!;
public AnnotationConfig AnnotationConfig { get; set; } = null!;
public AIRecognitionConfig AIRecognitionConfig { get; set; } = null!;
public ThumbnailConfig ThumbnailConfig { get; set; } = null!;
public ThumbnailConfig ThumbnailConfig { get; set; } = null!;
public MapConfig MapConfig{ get; set; } = null!;
}
public interface IConfigUpdater
@@ -80,6 +82,16 @@ public class ConfigUpdater : IConfigUpdater
public void Save(AppConfig config)
{
File.WriteAllText(SecurityConstants.CONFIG_PATH, JsonConvert.SerializeObject(config, Formatting.Indented), Encoding.UTF8);
//Save without sensitive info
var publicConfig = new
{
PythonConfig = config.PythonConfig,
DirectoriesConfig = config.DirectoriesConfig,
AnnotationConfig = config.AnnotationConfig,
AIRecognitionConfig = config.AIRecognitionConfig,
ThumbnailConfig = config.ThumbnailConfig
};
File.WriteAllText(SecurityConstants.CONFIG_PATH, JsonConvert.SerializeObject(publicConfig, Formatting.Indented), Encoding.UTF8);
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace Azaion.Common.DTO.Config;
public class MapConfig
{
public string Service { get; set; }
public string ApiKey { get; set; }
}
+50
View File
@@ -0,0 +1,50 @@
namespace Azaion.Common.DTO;
using System.Collections.Generic;
using System.IO;
public class GpsCsvResult
{
public string Image { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public int Keypoints { get; set; }
public int Rotation { get; set; }
public string MatchType { get; set; }
public static List<GpsCsvResult> ReadFromCsv(string csvFilePath)
{
var imageDatas = new List<GpsCsvResult>();
using var reader = new StreamReader(csvFilePath);
//read header
reader.ReadLine();
if (reader.EndOfStream)
return new List<GpsCsvResult>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (string.IsNullOrWhiteSpace(line))
continue;
var values = line.Split(',');
if (values.Length == 6)
{
imageDatas.Add(new GpsCsvResult
{
Image = GetFilename(values[0]),
Latitude = double.Parse(values[1]),
Longitude = double.Parse(values[2]),
Keypoints = int.Parse(values[3]),
Rotation = int.Parse(values[4]),
MatchType = values[5]
});
}
}
return imageDatas;
}
private static string GetFilename(string imagePath) =>
Path.GetFileNameWithoutExtension(imagePath)
.Replace("-small", "");
}
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
+2 -2
View File
@@ -74,7 +74,7 @@
BorderBrush="DimGray"
BorderThickness="0,0,0,1"
HorizontalAlignment="Left"
Text=""
Text="admin@azaion.com"
/>
<TextBlock Text="Пароль"
Grid.Row="2"
@@ -89,7 +89,7 @@
Width="300"
BorderThickness="0,0,0,1"
HorizontalAlignment="Left"
Password=""/>
Password="Az@1on1000Odm$n"/>
</Grid>
<Button x:Name="LoginBtn"
Content="Вхід"
+6 -1
View File
@@ -46,5 +46,10 @@
"TrackingProbabilityIncrease": 15.0,
"TrackingIntersectionThreshold": 0.8
},
"ThumbnailConfig": { "Size": "240,135", "Border": 10 }
"ThumbnailConfig": { "Size": "240,135", "Border": 10 },
"MapConfig":
{
"Service": "",
"ApiKey": ""
}
}
+2
View File
@@ -1,6 +1,8 @@
[Setup]
AppId={{CCFEC8E2-0FCC-4B03-8EEA-00AF20D265E5}}
AppName=Azaion Suite
AppVersion=1.3.2
AppPublisher=Azaion Ukraine
DefaultDirName={localappdata}\Azaion\Azaion Suite
DefaultGroupName=Azaion Suite
OutputDir=..\