|
|
|
@ -1,11 +1,21 @@ |
|
|
|
|
using System.Configuration; |
|
|
|
|
using System.Data; |
|
|
|
|
using System.IO; |
|
|
|
|
using System.Windows; |
|
|
|
|
using System.Windows.Input; |
|
|
|
|
using System.Windows.Media; |
|
|
|
|
using System.Windows.Media.Imaging; |
|
|
|
|
using Newtonsoft.Json; |
|
|
|
|
using Newtonsoft.Json.Linq; |
|
|
|
|
using SparkClient.Model.Common; |
|
|
|
|
using SparkClient.Model.Entity.ApiEntity; |
|
|
|
|
using SparkClient.Model.Helper; |
|
|
|
|
using SparkClient.Model.Services; |
|
|
|
|
using SparkClient.Views.Dialog; |
|
|
|
|
using SparkClient.ViewModel.BaseWindow; |
|
|
|
|
using SparkClient.ViewModel.Configuration; |
|
|
|
|
using SparkDotNetCore.DiamondScanner; |
|
|
|
|
using SparkDotNetCore.DiamondScanner.Entity; |
|
|
|
|
using MessageBox = SparkClient.Views.Dialog.MessageBox; |
|
|
|
|
|
|
|
|
|
namespace SparkClient.ViewModel.Grading; |
|
|
|
|
|
|
|
|
@ -13,7 +23,7 @@ public class GradingLoadingVM : BaseViewModel,IDisposable |
|
|
|
|
{ |
|
|
|
|
private double _progress; |
|
|
|
|
private SOCClientService _socClientService; |
|
|
|
|
|
|
|
|
|
public AlgorithmResultEntity Parameter; |
|
|
|
|
/// <summary> |
|
|
|
|
/// 进度 |
|
|
|
|
/// </summary> |
|
|
|
@ -38,6 +48,10 @@ public class GradingLoadingVM : BaseViewModel,IDisposable |
|
|
|
|
|
|
|
|
|
private CancellationTokenSource _progressCts; |
|
|
|
|
private CancellationTokenSource? _playbackCts; |
|
|
|
|
private Diamond _diamond; |
|
|
|
|
private Scanner _scanner; |
|
|
|
|
private CancellationTokenSource _completionCts; |
|
|
|
|
|
|
|
|
|
#region 图片播放控制 |
|
|
|
|
private PlayStatus _currentStatus = PlayStatus.Stopped; |
|
|
|
|
public PlayStatus CurrentStatus |
|
|
|
@ -57,7 +71,7 @@ public class GradingLoadingVM : BaseViewModel,IDisposable |
|
|
|
|
_ => "重播" // Stopped 状态 |
|
|
|
|
}; |
|
|
|
|
private CancellationTokenSource _cts; |
|
|
|
|
private int _playDelay = 200; // 默认播放速度 |
|
|
|
|
private int _playDelay = 100; // 默认播放速度 |
|
|
|
|
|
|
|
|
|
public ICommand PlayControlCommand { get; } |
|
|
|
|
public ICommand PreviousCommand { get; } |
|
|
|
@ -76,10 +90,27 @@ public class GradingLoadingVM : BaseViewModel,IDisposable |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public string[] ImagePaths { get; set; } |
|
|
|
|
public ImageSource CurrentImage { get; private set; } |
|
|
|
|
|
|
|
|
|
public bool ImageIsEnable { get; private set; } |
|
|
|
|
private ImageSource _currentImage; |
|
|
|
|
public ImageSource CurrentImage |
|
|
|
|
{ |
|
|
|
|
get => _currentImage; |
|
|
|
|
private set |
|
|
|
|
{ |
|
|
|
|
_currentImage = value; |
|
|
|
|
OnPropertyChanged(nameof(CurrentImage)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private bool _imageIsEnable; |
|
|
|
|
public bool ImageIsEnable |
|
|
|
|
{ |
|
|
|
|
get => _imageIsEnable; |
|
|
|
|
private set |
|
|
|
|
{ |
|
|
|
|
_imageIsEnable = value; |
|
|
|
|
OnPropertyChanged(nameof(ImageIsEnable)); // 触发通知 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endregion |
|
|
|
|
|
|
|
|
|
public GradingLoadingVM(string diamnondType, string diamondCode) |
|
|
|
@ -94,52 +125,213 @@ public class GradingLoadingVM : BaseViewModel,IDisposable |
|
|
|
|
|
|
|
|
|
_progressCts = new CancellationTokenSource(); |
|
|
|
|
_playbackCts = new CancellationTokenSource(); |
|
|
|
|
_completionCts = new CancellationTokenSource(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// 开始检测 |
|
|
|
|
/// </summary> |
|
|
|
|
public async Task<int> Start() |
|
|
|
|
{ |
|
|
|
|
//开始显示进度条 |
|
|
|
|
//切工仪通讯 拉取图片 延时...5秒 |
|
|
|
|
//播放图片 |
|
|
|
|
//图片拉取完毕---| |
|
|
|
|
// var configValue = ConfigurationHelper.ReadConfigValue("ProgressTime"); |
|
|
|
|
// int iProgTime = int.TryParse(configValue, out var result) ? result : 50000; |
|
|
|
|
// int stepTime = iProgTime / 97; |
|
|
|
|
// |
|
|
|
|
// for (int i = 0; i <= 97; i++) |
|
|
|
|
// { |
|
|
|
|
// _progressCts.Token.ThrowIfCancellationRequested(); |
|
|
|
|
// Progress = i; |
|
|
|
|
// await Task.Delay(stepTime, _progressCts.Token); |
|
|
|
|
// } |
|
|
|
|
var progress = RunProgressAsync(_progressCts.Token); |
|
|
|
|
public async Task<int> Start(int type = 0) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
try |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
var progress = RunProgressAsync(_progressCts.Token); |
|
|
|
|
if(type == 0){ |
|
|
|
|
_socClientService = new SOCClientService(); |
|
|
|
|
var processImage = _socClientService.ProcessImageCollectionAsync(); |
|
|
|
|
//通知页面可以播放图片 |
|
|
|
|
await processImage; |
|
|
|
|
|
|
|
|
|
if (!"ok".Equals(processImage.Result.Status)) |
|
|
|
|
if (!("ok".Equals(processImage.Result.Status) || "S000".Equals(processImage.Result.Status))) |
|
|
|
|
{ |
|
|
|
|
_progressCts.Cancel(); |
|
|
|
|
new MessageBox().Show(MultilingualHelper.getString(StatusCodes.GetConstantNameByValue(processImage.Result.Status))); |
|
|
|
|
new MessageBox().Show( |
|
|
|
|
MultilingualHelper.getString(StatusCodes.GetConstantNameByValue(processImage.Result.Status))); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
LoadImages(processImage.Result.Images); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (type == 1) |
|
|
|
|
{ |
|
|
|
|
List<string> mnFiles = new List<string>(); |
|
|
|
|
for (int i = 0; i < 100; i++) |
|
|
|
|
{ |
|
|
|
|
mnFiles.Add($"{i}.bmp"); |
|
|
|
|
} |
|
|
|
|
LoadImages(mnFiles); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
LoadImages(processImage.Result.Images); |
|
|
|
|
ImageIsEnable = true; |
|
|
|
|
StartPlayback(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Diamond diamond = new Diamond(); |
|
|
|
|
string circleSql = $"SELECT VALUE FROM CUTTER_CONFIG WHERE KEY = 'half_circle'"; |
|
|
|
|
DataTable circleTable = DataBaseHelper.ExecuteQuery(circleSql); |
|
|
|
|
object halfCircleValue = circleTable.Rows[0][0]; |
|
|
|
|
bool.TryParse(halfCircleValue.ToString(), out bool boolResult); |
|
|
|
|
bool half_circle = boolResult; |
|
|
|
|
|
|
|
|
|
//算法配置参数,初始化算法配置数据并获取 AlgorithmConfigJson |
|
|
|
|
var _algorithmConfigVM = new AlgorithmConfigVM(); |
|
|
|
|
_algorithmConfigVM.InitAlgorithmData(null); |
|
|
|
|
string algo_config = _algorithmConfigVM.AlgorithmConfigJson; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//图片根目录 |
|
|
|
|
string? image_file_base_path = ConfigurationManager.AppSettings["ImageFileBasePath"]; |
|
|
|
|
if (string.IsNullOrEmpty(image_file_base_path)) |
|
|
|
|
{ |
|
|
|
|
throw new InvalidOperationException("ImageFileBasePath is not configured in AppSettings."); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 获取 log4net 日志文件所在的目录 |
|
|
|
|
string? log4NetLogDirectory = |
|
|
|
|
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); |
|
|
|
|
// 构建C++ DLL 日志文件路径 |
|
|
|
|
string algorithm_log_path = Path.Combine(log4NetLogDirectory, "logs"); |
|
|
|
|
|
|
|
|
|
// 将所有变量拼接成一个 JSON 对象 |
|
|
|
|
JObject jsonData = new JObject( |
|
|
|
|
new JProperty("shape", _diamnondType.Split(" ")[0]), |
|
|
|
|
new JProperty("shape_mode", _diamnondType.Split(" ")[1]), |
|
|
|
|
new JProperty("image_file_base_path", image_file_base_path), |
|
|
|
|
new JProperty("image_files", ImagePaths), |
|
|
|
|
new JProperty("half_circle", half_circle), |
|
|
|
|
new JProperty("algorithm_log_path", algorithm_log_path), |
|
|
|
|
new JProperty("algo_config", JObject.Parse(algo_config)) |
|
|
|
|
); |
|
|
|
|
_scanner = new Scanner(diamond); |
|
|
|
|
var detectTask = _scanner.DetectAsyncByJsonStr(jsonData.ToString()); |
|
|
|
|
|
|
|
|
|
await detectTask; |
|
|
|
|
if (detectTask.Status == TaskStatus.RanToCompletion) |
|
|
|
|
{ |
|
|
|
|
return ReslutGen(detectTask); |
|
|
|
|
} |
|
|
|
|
await progress; |
|
|
|
|
return ReslutGen(detectTask); |
|
|
|
|
} |
|
|
|
|
catch(Exception ex) |
|
|
|
|
{ |
|
|
|
|
return -100; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private int ReslutGen(Task<DiaResult> detectTask) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
CompleteProgressQuicklyAsync(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (detectTask.Result.Status) |
|
|
|
|
{ |
|
|
|
|
case StatusCodes.AlgorithmFailed: |
|
|
|
|
new MessageBox().Show(MultilingualHelper.getString("AlgorithmFailed")); |
|
|
|
|
return -1; |
|
|
|
|
case StatusCodes.ImageFileReadFailure: |
|
|
|
|
new MessageBox().Show(MultilingualHelper.getString("ImageFileReadFailure")); |
|
|
|
|
return -1; |
|
|
|
|
case StatusCodes.JsonParseFailure: |
|
|
|
|
new MessageBox().Show(MultilingualHelper.getString("JsonParseFailure")); |
|
|
|
|
return -1; |
|
|
|
|
case StatusCodes.NoDiamond: |
|
|
|
|
new MessageBox().Show(MultilingualHelper.getString("NoDiamond")); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Progress = 100; |
|
|
|
|
|
|
|
|
|
string strParam = JsonConvert.SerializeObject(detectTask.Result); |
|
|
|
|
AlgorithmResultEntity parameter = JsonConvert.DeserializeObject<AlgorithmResultEntity>(strParam); |
|
|
|
|
if (parameter == null) |
|
|
|
|
{ |
|
|
|
|
new MessageBox().Show(MultilingualHelper.getString("JsonParseFailure")); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
try |
|
|
|
|
{ |
|
|
|
|
string parameterJson = JsonConvert.SerializeObject(parameter); |
|
|
|
|
parameterJson = JToken.Parse(parameterJson).ToString(); |
|
|
|
|
string outputPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "result"); |
|
|
|
|
if (!Directory.Exists(outputPath)) |
|
|
|
|
Directory.CreateDirectory(outputPath); |
|
|
|
|
string outputFilePath = $"{outputPath}/{_diamondCode}-{DateTime.Now:yyyyMMdd_HHmmss}.json"; |
|
|
|
|
using (var file = File.Create(outputFilePath)) |
|
|
|
|
using (StreamWriter stream = new StreamWriter(file)) |
|
|
|
|
{ |
|
|
|
|
stream.Write(parameterJson); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
catch (Exception ex) |
|
|
|
|
{ |
|
|
|
|
Logger.Error("output输出失败:" + ex.Message); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Parameter = parameter; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private async Task CompleteProgressSlowlyAsync() |
|
|
|
|
{ |
|
|
|
|
// 缓慢完成剩余3%(总耗时保持原速度的3倍) |
|
|
|
|
const int remainingSteps = 3; |
|
|
|
|
int stepTime = 500; // 自定义慢速步长 |
|
|
|
|
|
|
|
|
|
int current = (int)Progress; |
|
|
|
|
for (int i = 1; i <= remainingSteps; i++) |
|
|
|
|
{ |
|
|
|
|
if (_progressCts.IsCancellationRequested) break; |
|
|
|
|
UpdateProgress(current + i); |
|
|
|
|
await Task.Delay(stepTime); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private async Task CompleteProgressQuicklyAsync() |
|
|
|
|
{ |
|
|
|
|
// 取消原进度任务 |
|
|
|
|
_progressCts.Cancel(); |
|
|
|
|
|
|
|
|
|
// 快速完成剩余进度(0.5秒内完成) |
|
|
|
|
int current = (int)Progress; |
|
|
|
|
int remaining = 100 - current; |
|
|
|
|
if (remaining <= 0) return; |
|
|
|
|
|
|
|
|
|
int stepTime = Math.Max(50, 500 / remaining); // 动态计算步长 |
|
|
|
|
|
|
|
|
|
while (current < 100) |
|
|
|
|
{ |
|
|
|
|
current = Math.Min(current + 1, 100); |
|
|
|
|
UpdateProgress(current); |
|
|
|
|
await Task.Delay(stepTime); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
private void UpdateProgress(int value) |
|
|
|
|
{ |
|
|
|
|
// UI线程安全更新 |
|
|
|
|
Application.Current.Dispatcher.Invoke(() => |
|
|
|
|
{ |
|
|
|
|
Progress = value; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
private void Stop(object param) |
|
|
|
|
{ |
|
|
|
|
//询问?停止:忽略 |
|
|
|
|
MessageBox messageBox = new MessageBox(); |
|
|
|
|
MessageBoxResult showAsk = messageBox.ShowAsk("正在计算钻石数据,是否终止?"); |
|
|
|
|
if (showAsk == MessageBoxResult.OK) |
|
|
|
|
{ |
|
|
|
|
_scanner?.Cancel(); |
|
|
|
|
_progressCts.Cancel(); |
|
|
|
|
WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); |
|
|
|
|
this.Dispose(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private async Task RunProgressAsync(CancellationToken token) |
|
|
|
@ -263,13 +455,13 @@ public class GradingLoadingVM : BaseViewModel,IDisposable |
|
|
|
|
{ |
|
|
|
|
if (ImagePaths == null || CurrentIndex < 0 || CurrentIndex >= ImagePaths.Length) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
string? savePath = ConfigurationManager.AppSettings["ImageFileBasePath"]; |
|
|
|
|
var bitmap = new BitmapImage(); |
|
|
|
|
bitmap.BeginInit(); |
|
|
|
|
bitmap.CacheOption = BitmapCacheOption.OnLoad; |
|
|
|
|
bitmap.UriSource = new Uri(ImagePaths[CurrentIndex]); |
|
|
|
|
bitmap.UriSource = new Uri(savePath + @"\" + ImagePaths[CurrentIndex]); |
|
|
|
|
bitmap.EndInit(); |
|
|
|
|
bitmap.Freeze(); // 确保跨线程安全 |
|
|
|
|
bitmap.Freeze(); // 确保跨线程安全# |
|
|
|
|
|
|
|
|
|
CurrentImage = bitmap; |
|
|
|
|
OnPropertyChanged(nameof(CurrentImage)); |
|
|
|
|