using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Media;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Threading;
using Txgy.EWS.Client.Common.MessageEvents;
using Txgy.EWS.Client.Common;
using Txgy.EWS.Client.IBLL;
using Txgy.EWS.Client.ILog;
using Txgy.EWS.Client.Models;
using Txgy.EWS.Client.PageModule.Models;
using Unity;
using static Txgy.EWS.Client.Common.GlobalConfig;
using Txgy.EWS.Client.Entity;
using Newtonsoft.Json;
using System.IO;
using System.ComponentModel;
using Txgy.Microseismic.BaseLib.Models;
using SharpDX.Direct2D1.Effects;
using System.Windows.Media.Media3D;
using System.Windows.Media;
using Txgy.EWS.Client.PageModule.Common;
namespace Txgy.EWS.Client.PageModule.ViewModels
{
public class TitleViewModel : BindableBase
{
private readonly IEventAggregator _ea;
private readonly ISearchMsEventBLL searchMsEventBLL;
private readonly ILogHelper _logHelper;
Dispatcher _dispatcher;
private bool isCanRun = true;
SoundPlayer alarmPlayer = new SoundPlayer();
public DateTime SystemRunTime { get; set; }
///
/// 报警等级列表
///
public List ListAlarmLevel;
public List ListAlramMusic { get; set; }
private bool canPlayAlarmSound = true;
public bool CanPlayAlarmSound
{
get { return canPlayAlarmSound; }
set
{
SetProperty(ref canPlayAlarmSound, value);
}
}
public bool IsCanRun
{
get { return isCanRun; }
set
{
SetProperty(ref isCanRun, value);
}
}
///
/// 刷新间隔(s)
///
private int refreshInterval = 3;
public int RefreshInterval
{
get { return refreshInterval; }
set
{
SetProperty(ref refreshInterval, value);
}
}
private string curAlarmMusic;
public string CurAlarmMusic
{
get { return curAlarmMusic; }
set
{
SetProperty(ref curAlarmMusic, value);
alarmPlayer.SoundLocation = AppDomain.CurrentDomain.BaseDirectory + "audio\\" + curAlarmMusic;
alarmPlayer.LoadAsync();
}
}
private string runSpan = "0";
public string RunSpan
{
get { return runSpan; }
set
{
SetProperty(ref runSpan, value);
}
}
private int _receivedEventCount;
///
/// 接收到的事件数量
///
public int ReceivedEventCount
{
get { return _receivedEventCount; }
set
{
SetProperty(ref _receivedEventCount, value);
}
}
private int _alarmedEventCount = 0;
///
/// 已报警事件数量
///
public int AlarmedEventCount
{
get { return _alarmedEventCount; }
set
{
SetProperty(ref _alarmedEventCount, value);
}
}
private AlarmSetting _alarmSetting;
///
/// 报警参数
///
public AlarmSetting AlarmSetting
{
get { return _alarmSetting; }
set
{
SetProperty(ref _alarmSetting, value);
}
}
DateTime alarmEndTime = DateTime.Now;
//private double alarmThreshold = 1;
/////
///// 报警阈值:J
/////
//public double AlarmThreshold
//{
// get { return alarmThreshold; }
// set
// {
// SetProperty(ref alarmThreshold, value);
// }
//}
private AlarmLevelModel curAlarmLevel;
///
/// 当前预警等级
///
public AlarmLevelModel CurAlarmLevel
{
get { return curAlarmLevel; }
set
{
SetProperty(ref curAlarmLevel, value);
}
}
public ICommand ChangeMusicCommand
{
get => new Prism.Commands.DelegateCommand(() =>
{
LogObject.Log(MethodBase.GetCurrentMethod().Name).Info("===========End==============>>>");
});
}
public ICommand StartMonitoringCommand
{
//2023-02-21
get => new Prism.Commands.DelegateCommand(StartMonitorning);
}
public TitleViewModel(IUnityContainer unityContainer, IEventAggregator ea, ISearchMsEventBLL searchMsEventBLL, ILogHelper logHelper)
{
_dispatcher = unityContainer.Resolve();
this._ea = ea;
this._logHelper = logHelper;
this.searchMsEventBLL = searchMsEventBLL;
//AlarmThreshold = 1000;
using (System.IO.StreamReader sr = new System.IO.StreamReader(AppDomain.CurrentDomain.BaseDirectory +
System.Configuration.ConfigurationManager.AppSettings["AlarmSetting"].ToString()))
{
AlarmSetting = JsonConvert.DeserializeObject(sr.ReadToEnd());
}
//AlarmThreshold = AlarmSettingConfig.AlarmThreshold;
//RefreshInterval = AlarmSetting.RefreshInterval;
RefreshInterval = int.Parse(System.Configuration.ConfigurationManager.AppSettings["RefreshInterval"].ToString());
CurAlarmMusic = AlarmSetting.AlarmSound;
ListAlarmLevel = new List();
using (System.IO.StreamReader sr = new System.IO.StreamReader(AppDomain.CurrentDomain.BaseDirectory +
System.Configuration.ConfigurationManager.AppSettings["AlarmLevelConfig"].ToString()))
{
ListAlarmLevel = JsonConvert.DeserializeObject>(sr.ReadToEnd());
}
CurAlarmLevel = ListAlarmLevel.First(la => la.Level == 1);
_dispatcher.Invoke(new System.Action(() =>
{
GlobalData.CurAlarmLevelValue = CurAlarmLevel.Level;
GlobalData.CurAlarmLevelColor = new SolidColorBrush((Color)ColorConverter.ConvertFromString(CurAlarmLevel.ColorStr));
}));
ListAlramMusic = new List();
string[] alarmTmpArray = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "audio", "*.wav");
for (int i = 0; i < alarmTmpArray.Length; i++)
{
ListAlramMusic.Add(Path.GetFileName(alarmTmpArray[i]));
}
GlobalConfig.IsInitializing = true;
//初始化检索数据库数据
Task.Run(async () => {
string dataFilePath = GlobalConfig.ProjectConfig.MseedFilePath + "\\";
GlobalData.ListAlarmEventId = new List();
GlobalData.AlarmEvents = new List();
GlobalData.ReceivedEvents = new List();
GlobalData.LastEvent = new GridItemEventResult();
GlobalData.LastEvent.EventID = 0;
//预警平面参数
GlobalData.AlarmPlanList = new List();
GlobalData.MidEventList = new List();
DateTime timeNow = DateTime.Now;
var events = searchMsEventBLL.GetGridEvents(timeNow.AddMinutes(-GlobalConfig.LoadDataTimeLenMins), timeNow, -3, 0);
for (int i = 0; i < events.Count; i++)
{
await searchMsEventBLL.DownloadJsonDataAsync(events[i], dataFilePath, NotifyView);
GlobalConfig.InitializingCounter = ((i+1.0)/(double)events.Count)*100.0;
//await Console.Out.WriteLineAsync(GlobalConfig.InitializingCounter.ToString());
}
}).ContinueWith(t => { GlobalConfig.IsInitializing = false; });
//
}
void StartMonitorning()
{
if (!GlobalData.IsRunning)
{
this._logHelper.Debug(this, "===========End==============>>>");
//LogObject.Log(MethodBase.GetCurrentMethod().Name).Info("===========End==============>>>");
Task.WaitAll(GlobalData.TaskList.ToArray());
Task.Delay(2000);
}
else
{
this._logHelper.Debug(this, "===========Startup==============>>>");
//LogObject.Log(MethodBase.GetCurrentMethod().Name).Info("===========Startup==============>>>");
string dataFilePath = GlobalConfig.ProjectConfig.MseedFilePath + "\\";
AlarmedEventCount = 0;
SystemRunTime = DateTime.Now;
//DateTime alarmTime = DateTime.Now;
DateTime eventFreqTime = DateTime.Now;
#region 预警平面参数
//GlobalData.AlarmPlanList = new List();
//GlobalData.MidEventList = new List();
#endregion
//2023-03-15新事件查询,每10秒查询一次,如果有新事件,需要下载二进制数据,数据大小:5m左右,因为是远程数据库,下载需要5秒左右。
//2023-04-25已修正
var taskAlarm = Task.Factory.StartNew(new System.Action(async () =>
{
if (GlobalConfig.IsDesign)
{
alarmEndTime = new DateTime(2023, 4, 1);
RefreshInterval = GlobalConfig.DRefreshInterval;
// await Task.Delay(3000);
int qid = 54171;
while (GlobalData.IsRunning)
{
try
{
await Task.Delay(500).ContinueWith(async t =>
{
//Console.WriteLine($"查询开始时间:{DateTime.Now.ToString("HH:mm:ss.FFF")}");
//var events = searchMsEventBLL.GetLastEvents(qid);
var events = searchMsEventBLL.GetGridEvents(alarmEndTime, alarmEndTime.AddSeconds(3600), -3, 0);
foreach (var item in events)
{
await searchMsEventBLL.DownloadJsonDataAsync(item, dataFilePath, NotifyView);
//Console.WriteLine(item.EventID);
}
//Console.WriteLine($"查询开始时间:{DateTime.Now.ToString("HH:mm:ss.FFF")}");
//alarmEndTime = alarmEndTime.AddMinutes(10);
//await searchMsEventBLL.QueryAndDownloadDataAsync(qid, alarmEndTime, dataFilePath, NotifyView);
alarmEndTime = alarmEndTime.AddMinutes(60);
qid++;
//alarmEndTime = DateTime.Parse(GlobalData.LastEvent.EventTime);
//alarmEndTime =GlobalData.LastEvent.OTime;
});
}
catch (Exception ex)
{
string strLog = String.Format("查询线程,{0}", ex.StackTrace);
this._logHelper.Error(this, strLog);
throw;
}
}
}
else
{
//获取最后一个事件
GridItemEventResult lastEvent = searchMsEventBLL.GetLastTopEvents(1)[0];
GlobalData.ListAlarmEventId.Add(lastEvent.EventID);
GlobalData.LastEvent = new GridItemEventResult();
GlobalData.LastEvent.EventID = lastEvent.EventID;
GlobalData.LastEvent.EventTime = lastEvent.EventTime;
GlobalData.LastEvent.OTime = DateTime.Parse(lastEvent.EventTime);
while (GlobalData.IsRunning)
{
try
{
await Task.Delay(RefreshInterval * 1000).ContinueWith(async t =>
{
//2023-04-25
//await searchMsEventBLL.QueryAndDownloadDataAsync(GlobalData.LastEvent.EventID, dataFilePath, NotifyView);
//_logHelper.Debug($"{DateTime.Now.ToString("G")}:事件查询完成", "");
//2023-04-26
var events = searchMsEventBLL.GetLastEvents(GlobalData.LastEvent.EventID);
foreach (var item in events)
{
await searchMsEventBLL.DownloadJsonDataAsync(item, dataFilePath, NotifyView);
//Console.WriteLine(item.EventID);
}
});
}
catch (Exception ex)
{
string strLog = String.Format("查询线程,{0}", ex.StackTrace);
this._logHelper.Error(this, strLog);
//string strInfoLog = String.Format("事件查询异常结束,系统运行时长:{0}", (DateTime.Now - SystemRunTime).TotalSeconds);
//this._logHelper.Error(this, strInfoLog);
//LogObject.Log(MethodBase.GetCurrentMethod().Name).Error(ex.Message);
//throw;
}
}
}
}));
//事件数量统计查询,每60秒查询一次,大多数情况运行正常,如果遇到网络不好的情况或者新事件查询功能在下载数据,数据库连接会出问题。
var taskEventFreq = Task.Factory.StartNew(new System.Action(async () =>
{
if (GlobalConfig.IsDesign)
{
eventFreqTime = GlobalConfig.DStartTime;
while (GlobalData.IsRunning)
{
try
{
await Task.Delay(10000).ContinueWith(async t =>
{
DateTime st = eventFreqTime.AddSeconds(-3600);
DateTime et = eventFreqTime;
int StatCount = await searchMsEventBLL.StatEventCountAsync(st, et);
//通知更新一小时前事件数量
this._ea.GetEvent().Publish(StatCount);
eventFreqTime = eventFreqTime.AddSeconds(3600);
});
}
catch (Exception ex)
{
string strLog = String.Format("统计线程,{0}", ex.StackTrace);
Console.WriteLine(strLog);
this._logHelper.Error(this, strLog);
//throw;
}
}
}
else
{
while (GlobalData.IsRunning)
{
try
{
await Task.Delay(60000).ContinueWith(async t =>
{
DateTime st = eventFreqTime.AddSeconds(-3600);
DateTime et = eventFreqTime;
int StatCount = await searchMsEventBLL.StatEventCountAsync(st, et);
//通知更新一小时前事件数量
this._ea.GetEvent().Publish(StatCount);
eventFreqTime = DateTime.Now;
});
}
catch (Exception ex)
{
string strLog = String.Format("统计线程,{0}", ex.StackTrace);
//Console.WriteLine(strLog);
this._logHelper.Error(this, strLog);
//throw;
}
}
}
}));
//更新监控时长
var taskRunTime = Task.Factory.StartNew(new System.Action(async () =>
{
while (GlobalData.IsRunning)
{
TimeSpan ts = DateTime.Now - SystemRunTime;
RunSpan = ts.Days.ToString() + "天" + ts.Hours.ToString() + "小时" + ts.Minutes.ToString() + "分" + ts.Seconds.ToString() + "秒";
await Task.Delay(1000);
}
}));
GlobalData.TaskList.Add(taskAlarm);
GlobalData.TaskList.Add(taskEventFreq);
GlobalData.TaskList.Add(taskRunTime);
}
}
void NotifyView(GridItemEventResult gier)
{
_logHelper.Debug($"{DateTime.Now.ToString("G")}:回调执行", "回调执行完成");
//Console.WriteLine($"事件ID:{gier.EventID}下载回调成功,下载结束时间:{DateTime.Now.ToString("HH:mm:ss.FFF")}!");
if (GlobalData.ListAlarmEventId.Contains(gier.EventID))
{
// Console.WriteLine($"事件ID:{gier.EventID}已存在,返回!");
_logHelper.Debug($"{DateTime.Now.ToString("G")}:回调执行", $"事件ID:{gier.EventID}已存在,返回");
return;
}
GlobalData.ListAlarmEventId.Add(gier.EventID);
if (gier.EventID > GlobalData.LastEvent.EventID)
{
gier.DominantFreq = GlobalData.GetDominFreq(gier.EventTime);
GlobalData.LastEvent = new GridItemEventResult();
GlobalData.LastEvent.EventID = gier.EventID;
GlobalData.LastEvent.EventTime = gier.EventTime;
GlobalData.LastEvent.OTime = gier.OTime;
_logHelper.Debug($"{DateTime.Now.ToString("G")}:回调执行", $"事件ID:{gier.EventID}LastEvent事件更新。");
//通知主频更新
this._ea.GetEvent().Publish(gier.DominantFreq);
_logHelper.Debug($"{DateTime.Now.ToString("G")}:回调执行", $"事件ID:{gier.EventID}LastEvent页面更新。");
}
#region 通知页面更新
//通知预警页面图表变化
this._ea.GetEvent().Publish(gier);
//计算震源机制
EventFunc.ComputeFM(gier);
//计算主频
gier.DominantFreq = GlobalData.GetDominFreq(gier.EventTime);
//从接收事件列表中删除超过指定时间范围的数据
var timeoutReceivedEvents = GlobalData.ReceivedEvents.FindAll(re => (DateTime.Now - DateTime.Parse(re.EventTime)).TotalSeconds >= GlobalData.EventShowTimeout).ToArray();
if (timeoutReceivedEvents.Length > 0)
{
for (int i = timeoutReceivedEvents.Length - 1; i >= 0; i--)
{
GlobalData.ReceivedEvents.Remove(timeoutReceivedEvents[i]);
}
}
if (gier.ML >= GlobalConfig.MidML)
{
GlobalData.MidEventList.Add(gier);
GlobalData.MidEventCount = GlobalData.MidEventList.Count;
SearchPlane(gier);
}
//添加到已接收事件列表
if (!GlobalData.ReceivedEvents.Contains(gier))
{
GlobalData.ReceivedEvents.Add(gier);
GlobalData.PlanesAddEvent(gier);
this._ea.GetEvent().Publish(gier);
}
ReceivedEventCount = GlobalData.ReceivedEvents.Count();
//检查预警平面是否失效
if (GlobalConfig.IsDesign)
{
foreach (var plane in GlobalData.AlarmPlanList)
{
if (plane.Valid)
{
//Debug.WriteLine((moniCurTime - plane.Event1.OTime).TotalSeconds);
bool ec1 = (alarmEndTime - DateTime.Parse(plane.Event1.EventTime)).TotalSeconds > GlobalData.ValidSecend;
if (ec1)
{
//Debug.WriteLine($"ec1:{(moniCurTime - plane.Event1.OTime).TotalSeconds}");
plane.Valid = false;
continue;
}
bool ec2 = (alarmEndTime - DateTime.Parse(plane.Event2.EventTime)).TotalSeconds > GlobalData.ValidSecend;
if (ec2)
{
//Debug.WriteLine($"ec2:{(moniCurTime - plane.Event2.OTime).TotalSeconds}");
plane.Valid = false;
continue;
}
bool ec3 = (alarmEndTime - DateTime.Parse(plane.Event3.EventTime)).TotalSeconds > GlobalData.ValidSecend;
if (ec3)
{
//Debug.WriteLine($"ec3:{(moniCurTime - plane.Event3.OTime).TotalSeconds}");
plane.Valid = false;
//continue;
}
}
}
}
else
{
foreach (var plane in GlobalData.AlarmPlanList)
{
if (plane.Valid)
{
//Debug.WriteLine((moniCurTime - plane.Event1.OTime).TotalSeconds);
bool ec1 = (DateTime.Now - DateTime.Parse(plane.Event1.EventTime)).TotalSeconds > GlobalData.ValidSecend;
if (ec1)
{
//Debug.WriteLine($"ec1:{(moniCurTime - plane.Event1.OTime).TotalSeconds}");
plane.Valid = false;
continue;
}
bool ec2 = (DateTime.Now - DateTime.Parse(plane.Event2.EventTime)).TotalSeconds > GlobalData.ValidSecend;
if (ec2)
{
//Debug.WriteLine($"ec2:{(moniCurTime - plane.Event2.OTime).TotalSeconds}");
plane.Valid = false;
continue;
}
bool ec3 = (DateTime.Now - DateTime.Parse(plane.Event3.EventTime)).TotalSeconds > GlobalData.ValidSecend;
if (ec3)
{
//Debug.WriteLine($"ec3:{(moniCurTime - plane.Event3.OTime).TotalSeconds}");
plane.Valid = false;
//continue;
}
}
}
}
//Console.WriteLine($"删除前平面数量:{GlobalData.AlarmPlanList.Count}");
//删除以失效的平面
GlobalData.AlarmPlanList.RemoveAll(x => x.Valid == false);
GlobalData.AlarmPlanCount = GlobalData.AlarmPlanList.Count();
//Console.WriteLine($"删除后平面数量:{GlobalData.AlarmPlanList.Count}");
//统计预警平面的事件每小时频度
int maxFrequency = 0;
foreach (var plane in GlobalData.AlarmPlanList)
{
if (plane.Valid)
{
var hourlyFrequency = plane.InRangeEventList
.GroupBy(e => new DateTime(e.OTime.Year, e.OTime.Month, e.OTime.Day, e.OTime.Hour, 0, 0))
.Select(g => new
{
Hour = g.Key,
Frequency = g.Count()
})
.ToList();
if (hourlyFrequency != null)
{
if (hourlyFrequency.Count > 0)
{
if (hourlyFrequency[hourlyFrequency.Count - 1].Frequency > maxFrequency)
{
maxFrequency = hourlyFrequency[hourlyFrequency.Count - 1].Frequency;
}
}
}
plane.EventFrequencyList = new List();
//Debug.WriteLine($"平面ID:{plane.ID}\t当前时间:{moniCurTime.ToString("G")}\t最大连续:{plane.MaxUnbrokenSameFocalCount}");
if (!GlobalData.unbrokenSameFocalList.Contains(plane.MaxUnbrokenSameFocalCount))
{
GlobalData.unbrokenSameFocalList.Add(plane.MaxUnbrokenSameFocalCount);
}
if (plane.MaxUnbrokenSameFocalCount < GlobalData.maxUnbrokenFocal)
{
GlobalData.maxUnbrokenFocal = plane.MaxUnbrokenSameFocalCount;
}
foreach (var item in hourlyFrequency)
{
plane.EventFrequencyList.Add(new EventFrequency { StartTime = item.Hour, Frequency = item.Frequency });
if (item.Frequency > GlobalData.maxFrequency)
{
GlobalData.maxFrequency = item.Frequency;
}
if (!GlobalData.frequencyList.Contains(item.Frequency))
{
GlobalData.frequencyList.Add(item.Frequency);
}
//Debug.WriteLine($"小时:{item.Hour}\t频度:{item.Frequency}");
}
//Debug.WriteLine("---------------------------------------------");
}
}
if (maxFrequency > 40)
{
CurAlarmLevel = ListAlarmLevel.First(la => la.Level == 4);
}
else if (maxFrequency > 30)
{
CurAlarmLevel = ListAlarmLevel.First(la => la.Level == 3);
}
else if (maxFrequency > 20)
{
CurAlarmLevel = ListAlarmLevel.First(la => la.Level == 2);
}
else if (maxFrequency > 10)
{
CurAlarmLevel = ListAlarmLevel.First(la => la.Level == 1);
}
_dispatcher.Invoke(new System.Action(() =>
{
GlobalData.CurAlarmLevelValue = CurAlarmLevel.Level;
GlobalData.CurAlarmLevelColor = new SolidColorBrush((Color)ColorConverter.ConvertFromString(CurAlarmLevel.ColorStr));
}));
//Console.WriteLine($"maxFre:{maxFrequency}\tLevel:{GlobalData.CurAlarmLevelValue}\tColor:{CurAlarmLevel.ColorStr}");
//如果能量大于设定值,通知报警
if (gier.Energy >= AlarmSetting.AlarmThreshold)
{
//添加到报警事件列表
if (!GlobalData.AlarmEvents.Contains(gier))
{
//通知报警事件更新
this._ea.GetEvent().Publish(gier);
//CurAlarmLevel = ListAlarmLevel.First(lal => lal.MaxEnergy >= gier.Energy && lal.MinEnergy <= gier.Energy);
//声音报警
if (canPlayAlarmSound)
{
alarmPlayer.PlaySync();
}
if (!GlobalConfig.IsDesign)
{
//从预警事件列表中删除超过指定时间范围的数据
var timeoutAlarmEvents = GlobalData.AlarmEvents.FindAll(re => (DateTime.Now - DateTime.Parse(re.EventTime)).TotalSeconds >= GlobalData.EventShowTimeout).ToArray();
if (timeoutAlarmEvents.Length > 0)
{
for (int i = timeoutAlarmEvents.Length - 1; i >= 0; i--)
{
GlobalData.AlarmEvents.Remove(timeoutAlarmEvents[i]);
}
}
}
//报警数量
AlarmedEventCount = GlobalData.AlarmEvents.Count;
}
//AlarmRecordEntity arent = new AlarmRecordEntity();
//arent.EventId = gier.EventID;
//arent.AlarmTime = gier.OriginTime;
//arent.AlarmLevel = CurAlarmLevel.Level;
//arent.Energy = gier.Energy;
//写入报警记录
//var haveAre = fsqlSqLite.Select().Where(are => are.EventId == arent.EventId).ToOne();
//if (haveAre == null)
//{
// fsqlSqLite.Insert(arent).ExecuteIdentityAsync();
//}
#endregion
}
}
public void SearchPlane(GridItemEventResult newEvent)
{
if (GlobalData.MidEventList != null)
{
if (GlobalData.MidEventList.Count > 2)
{
for (int i = 0; i < GlobalData.MidEventList.Count - 1; i++)
{
for (int j = i + 1; j < GlobalData.MidEventList.Count; j++)
{
if (GlobalData.MidEventList[i].EventID != GlobalData.MidEventList[j].EventID && GlobalData.MidEventList[i].EventID != newEvent.EventID &&
GlobalData.MidEventList[j].EventID != newEvent.EventID)
{
Plane sf = CreatePlane(GlobalData.AlarmPlanList.Count + 1, GlobalData.MidEventList[i], GlobalData.MidEventList[j], newEvent);
GlobalData.AlarmPlanList.Add(sf);
}
}
}
}
}
}
public Plane CreatePlane(int id, GridItemEventResult pe1, GridItemEventResult pe2, GridItemEventResult pe3)
{
Plane sur = new Plane();
sur.ID = id;
sur.Event1 = pe1;
sur.Pos1 = AbsoluteCoord2RelativeCoord(pe1);
sur.Event2 = pe2;
sur.Pos2 = AbsoluteCoord2RelativeCoord(pe2);
sur.Event3 = pe3;
sur.Pos3 = AbsoluteCoord2RelativeCoord(pe3);
sur.focal = new Random().Next(3);
sur.SetMNPPara();
return sur;
}
}
}