using System; using System.Collections.Generic; using System.Text; using System.IO; using Misc; using System.Data; using System.Xml; using System.ComponentModel; using System.Collections.ObjectModel; using System.Linq; using System.Xml.Linq; using FLY.Thick.Base.Common; using FLY.Thick.Base.IService; namespace FLY.Thick.Base.Server { public class BoltMapImg : IBoltMapService, INotifyPropertyChanged, Misc.ISaveToXml, IBoltMapBase { #region 成员变量 #region 数据文件需要保存的数据项 private int _firstBoltNo; /// <summary> /// 1st 分区号,之后的不断加1 /// </summary> public int FirstBoltNo { get { return _firstBoltNo; } set { _firstBoltNo = value; NotifyPropertyChanged("FirstBoltNo"); } } private BORDER_TYPE bordertype; /// <summary> /// 找边界,边界类型 /// </summary> public BORDER_TYPE BorderType { get { return bordertype; } set { if (bordertype != value) { bordertype = value; NotifyPropertyChanged("BorderType"); } } } private int borderboltno_b; /// <summary> /// 开始边界分区号 /// </summary> public int BorderBoltNo_B { get { return borderboltno_b; } set { if (borderboltno_b != value) { borderboltno_b = value; NotifyPropertyChanged("BorderBoltNo_B"); } } } private int borderboltno_e; /// <summary> /// 结束边界分区号 /// </summary> public int BorderBoltNo_E { get { return borderboltno_e; } set { if (borderboltno_e != value) { borderboltno_e = value; NotifyPropertyChanged("BorderBoltNo_E"); } } } public ObservableCollection<Range> _bolts = new ObservableCollection<Range>(); public ObservableCollection<Range> Bolts { get { return _bolts; } } private int smooth; public int Smooth { get { return smooth; } set { if (smooth != value) { smooth = value; NotifyPropertyChanged("Smooth"); } } } #endregion #region 只用于描述 Bolts,没什么用 private int lastboltno; /// <summary> /// 最后一个分区号 /// </summary> public int LastBoltNo { get { return lastboltno; } protected set { if (lastboltno != value) { lastboltno = value; NotifyPropertyChanged("LastBoltNo"); } } } private int boltinterval; /// <summary> /// 平均分区间隔 /// </summary> public int BoltInterval { get { return boltinterval; } set { if (boltinterval != value) { boltinterval = value; NotifyPropertyChanged("BoltInterval"); } } } private int boltwidth; /// <summary> /// 平均分区宽度 /// </summary> public int BoltWidth { get { return boltwidth; } protected set { if (boltwidth != value) { boltwidth = value; NotifyPropertyChanged("BoltWidth"); } } } private int posbegin; /// <summary> /// 脉冲范围 开始 /// </summary> public int PosBegin { get { return posbegin; } protected set { if (posbegin != value) { posbegin = value; NotifyPropertyChanged("PosBegin"); } } } private int posend; /// <summary> /// 脉冲范围 结束 /// </summary> public int PosEnd { get { return posend; } protected set { if (posend != value) { posend = value; NotifyPropertyChanged("PosEnd"); } } } #endregion #endregion /// <summary> /// 动态分区 /// </summary> private DynBoltAD dyn; private BoltMapHelper helper; public event ActiveEventHandler ActiveEvent; public BoltMapImg() { dyn = new DynBoltAD(this); helper = new BoltMapHelper(this); } public BoltMapImg(string param_path) { if (!string.IsNullOrEmpty(param_path)) Path = param_path; else Path = "boltmap.xml"; //设置默认值---------------------------------------------------------------- EasyCreate(1, 50, 9000); //------------------------------------------------------------------------------- if (!Load(null)) { } apply2(); } static BoltMapImg() { Misc.SaveToXmlHepler.Regist(typeof(BoltMapImg)); } private void apply2() { LastBoltNo = FirstBoltNo + Bolts.Count() - 1; PosBegin = Bolts.First().Begin; PosEnd = Bolts.Last().End; BoltWidth = (int)Bolts.Average((r) => r.Width); List<int> buf = new List<int>(); for (int i = 1; i < Bolts.Count(); i++) { int interval = Bolts[i].Mid - Bolts[i - 1].Mid; buf.Add(interval); } BoltInterval = (int)buf.Average(); //检测 膜边界参数 if (BorderBoltNo_B < FirstBoltNo) BorderBoltNo_B = FirstBoltNo; if (BorderBoltNo_E > LastBoltNo) BorderBoltNo_E = LastBoltNo; if (BorderBoltNo_B > BorderBoltNo_E) { BorderBoltNo_B = FirstBoltNo; BorderBoltNo_E = LastBoltNo; } } public void Apply() { apply2(); Save(null); //触发事件!!!! //TODO if (ActiveEvent != null) ActiveEvent(this); } public void ApplyWithoutSave() { apply2(); //触发事件!!!! //TODO if (ActiveEvent != null) ActiveEvent(this); } public void ApplyBorder() { Save(null); } public void Clear() { Bolts.Clear(); } public int NBolts { get { return Bolts.Count; } } public void EasyCreate(int boltno1st, int boltcnt, int poslen) { Bolts.Clear(); int b = 0; for (int i = 0; i < boltcnt; i++) { Bolts.Add(new Range() { Begin = b, End = b + poslen / boltcnt - 1 }); b = Bolts.Last().End + 1; } FirstBoltNo = boltno1st; BorderType = BORDER_TYPE.Null; BorderBoltNo_B = boltno1st; BorderBoltNo_E = boltno1st + boltcnt - 1; //Apply(); } public void EasyCreate2(int boltno1st, int boltwidth, int poslen) { Bolts.Clear(); int b = 0; int e = b + boltwidth-1; while (e < poslen) { Bolts.Add(new Range() { Begin = b, End = e }); b = e + 1; e = b + boltwidth - 1; } FirstBoltNo = boltno1st; BorderType = BORDER_TYPE.Null; BorderBoltNo_B = boltno1st; BorderBoltNo_E = boltno1st + Bolts.Count - 1; //Apply(); } #region INotifyPropertyChanged 成员 protected void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; #endregion #region ISaveToXml 成员 public string[] GetSavePropertyNames() { return new string[]{ "FirstBoltNo", "Bolts", "BorderType", "BorderBoltNo_B", "BorderBoltNo_E", "BorderBoltNo_M", "Smooth" }; } #endregion #region ITDParam 成员 public string FileName { get; set; } public string DirectoryName { get; set; } public string Path { get { if (string.IsNullOrEmpty(DirectoryName)) return FileName; else return DirectoryName + @"\" + FileName; } set { DirectoryName = System.IO.Path.GetDirectoryName(value); FileName = System.IO.Path.GetFileName(value); } } public bool Load(string name) { if (name != null) FileName = name; return Misc.SaveToXmlHepler.Load(Path, this); } public bool Save(string name) { if (name != null) FileName = name; return Misc.SaveToXmlHepler.Save(Path, this); } #endregion #region IBoltMapBase public void GetBolts(out int boltno1st, out IEnumerable<Range> bolts) { boltno1st = FirstBoltNo; bolts = Bolts; } public void GetScanRange(Range boltno, out int posBegin, out int posEnd) { int boltindex = boltno.Begin - FirstBoltNo; if (boltindex < 0) boltindex = 0; else if (boltindex >= NBolts) boltindex = NBolts - 1; posBegin = Bolts[boltindex].Begin; boltindex = boltno.End - FirstBoltNo; if (boltindex < 0) boltindex = 0; else if (boltindex >= NBolts) boltindex = NBolts - 1; posEnd = Bolts[boltindex].End; } public int GetBoltIndex_fromPos(int pos) { return pos / BoltWidth; } #region 用于动态生成分区数据 public void InitBoltAD() { dyn.Init(); } public bool UpdateBoltAD(int[] data, int start_pos, int posOfGrid, Misc.DIRECTION direction, out int start_boltIndex, out int[] boltAD) { return dyn.UpdateBoltAD(data, start_pos, posOfGrid, direction, out start_boltIndex, out boltAD); } #endregion #region 根据边界调整分区 public void InitExChange() { this.helper.InitExChange(); } public void CalExChange(Misc.DIRECTION direction, Range bolt_r) { CalExChange(direction, bolt_r.Begin, bolt_r.End); } public void CalExChange(Misc.DIRECTION direction, int borderPosBegin, int borderPosEnd) { int idx = 0; if (direction == Misc.DIRECTION.BACKWARD) idx = 1; FLY.Thick.Base.Server.BoltMapHelper.ExChange exchange = helper.mExChange[idx]; exchange.Init(); int borderPosMid = (borderPosBegin + borderPosEnd) / 2; int org_borderPosBegin; int org_borderPosEnd; int org_borderPosMid; int borderboltindex_b = BorderBoltNo_B - FirstBoltNo; int borderboltindex_e = BorderBoltNo_E - FirstBoltNo; if (borderboltindex_b < 0) borderboltindex_b = 0; else if (borderboltindex_b >= NBolts) borderboltindex_b = 0; if (borderboltindex_e < borderboltindex_b) borderboltindex_e = NBolts; else if (borderboltindex_e >= NBolts) borderboltindex_e = NBolts; switch (BorderType) { case BORDER_TYPE.Null: { } break; case BORDER_TYPE.BeginEnd: { org_borderPosBegin = Bolts[borderboltindex_b].Begin; org_borderPosEnd = Bolts[borderboltindex_e].End; exchange.Amp = ((double)(borderPosEnd - borderPosBegin)) / (org_borderPosEnd - org_borderPosBegin); exchange.Offset = (int)(borderPosBegin - org_borderPosBegin * exchange.Amp); } break; case BORDER_TYPE.Begin: { org_borderPosBegin = Bolts[borderboltindex_b].Begin; exchange.Offset = (int)(borderPosBegin - org_borderPosBegin * exchange.Amp); } break; case BORDER_TYPE.End: { org_borderPosEnd = Bolts[borderboltindex_e].End; exchange.Offset = (int)(borderPosEnd - org_borderPosEnd * exchange.Amp); } break; case BORDER_TYPE.Mid: { org_borderPosMid = (Bolts[borderboltindex_b].Begin + Bolts[borderboltindex_e].End) / 2; exchange.Offset = (int)(borderPosMid - org_borderPosMid * exchange.Amp); } break; } } public int PositionExchange(Misc.DIRECTION direction, int position) { return helper.PositionExchange(direction, position); } public int BoltExchange(Misc.DIRECTION direction, int bolt_pos) { return helper.BoltExchange(direction, bolt_pos); } #endregion public int[] Map(Misc.DIRECTION direction, int posBegin, int posOfGrid, int[] dat) { return helper.Map(direction, posBegin, posOfGrid, dat); } #endregion } public class DynBoltAD { #region 动态扫描时,提前算分区的AD值,正常时 通过 grid数据划分的 private const int NBOLTS_AD = 20; private int[] boltADIndex = new int[NBOLTS_AD]; private int[] boltADSum = new int[NBOLTS_AD]; private int[] boltADCnt = new int[NBOLTS_AD]; #endregion IBoltMapBase boltmap; public DynBoltAD(IBoltMapBase boltmap) { this.boltmap = boltmap; } public void Init() { for (int i = 1; i < NBOLTS_AD; i++) { boltADIndex[i] = -1; boltADSum[i] = boltADCnt[i] = 0; } } private bool UpdateBoltAD(int ad, int position, Misc.DIRECTION direction, out int boltIndex, out int boltAD) { boltAD = Misc.MyBase.NULL_VALUE; boltIndex = -1; bool ret = false; int min, max; int i, j; int curr_boltno1st;//当前分区表 1st分区号 IEnumerable<Range> curr_bolts;//当前分区表 int curr_nbolts;//当前分区总数 boltmap.GetBolts(out curr_boltno1st, out curr_bolts); curr_nbolts = curr_bolts.Count(); position = boltmap.PositionExchange(direction, position); switch (direction) { case Misc.DIRECTION.FORWARD: max = int.MinValue; for (i = 1; i < NBOLTS_AD; i++) { int end; if (boltADIndex[i] < 0) continue; if (boltADIndex[i] >= curr_nbolts) { //这个是有问题的 continue; } if (boltADIndex[i] > max) max = boltADIndex[i]; end = curr_bolts.ElementAt(boltADIndex[i]).End; if (position > end) { int temp = Misc.MyBase.NULL_VALUE; if (boltADCnt[i] > 0) temp = boltADSum[i] / boltADCnt[i]; boltAD = temp; boltIndex = boltADIndex[i]; ret = true; boltADIndex[i] = -1; boltADSum[i] = boltADCnt[i] = 0; } else { if (ad != Misc.MyBase.NULL_VALUE) { boltADSum[i] += ad; boltADCnt[i]++; } } } if (max == int.MinValue) { FindBolt(position); } else { for (i = 1; max + i < curr_nbolts; i++) { if (position > curr_bolts.ElementAt(max + i).Begin) { if ((j = GetFreeBoltAD()) < 0) { break; } else { boltADIndex[j] = max + i; if (ad != Misc.MyBase.NULL_VALUE) { boltADCnt[j] = 1; boltADSum[j] = ad; } else { boltADCnt[j] = 0; boltADSum[j] = 0; } } } else break; } } break; case Misc.DIRECTION.BACKWARD: min = int.MaxValue; for (i = 1; i < NBOLTS_AD; i++) { if (boltADIndex[i] < 0) continue; if (boltADIndex[i] >= curr_nbolts) { //这个是有问题的 continue; } if (boltADIndex[i] < min) min = boltADIndex[i]; if ((position < (curr_bolts.ElementAt(boltADIndex[i]).Begin)) || (position <= 0)) { int temp = Misc.MyBase.NULL_VALUE; if (boltADCnt[i] > 0) { temp = boltADSum[i] / boltADCnt[i]; } boltAD = temp; boltIndex = boltADIndex[i]; ret = true; boltADIndex[i] = -1; boltADSum[i] = boltADCnt[i] = 0; } else { if (ad != Misc.MyBase.NULL_VALUE) { boltADSum[i] += ad; boltADCnt[i]++; } } } if (min == int.MaxValue) FindBolt(position); else { for (i = 1; min - i >= 0; i++) { if (position < curr_bolts.ElementAt(min - i).End) { if ((j = GetFreeBoltAD()) < 0) break; else { boltADIndex[j] = min - i; if (ad != Misc.MyBase.NULL_VALUE) { boltADCnt[j] = 1; boltADSum[j] = ad; } else { boltADCnt[j] = 0; boltADSum[j] = 0; } } } else break; } } break; } return ret; } private void FindBolt(int position) { int curr_boltno1st;//当前分区表 1st分区号 IEnumerable<Range> curr_bolts;//当前分区表 int curr_nbolts; boltmap.GetBolts(out curr_boltno1st, out curr_bolts); curr_nbolts = curr_bolts.Count(); int i, j = 1; for (i = 0; i < curr_nbolts; i++) { if (position > (curr_bolts.ElementAt(i).End)) continue; if ((position < (curr_bolts.ElementAt(i).Begin)) || (position <= 0)) break; boltADIndex[j] = i; boltADSum[j] = boltADCnt[j] = 0; j++; if (j >= NBOLTS_AD) break; } } private int GetFreeBoltAD() { for (int i = 1; i < NBOLTS_AD; i++) if (boltADIndex[i] < 0) return i; return -1; } public bool UpdateBoltAD(int[] data, int start_pos, int posOfGrid, Misc.DIRECTION direction, out int start_boltIndex, out int[] boltAD) { int nbolts = boltmap.NBolts; int start_grid = start_pos / posOfGrid; start_boltIndex = -1; List<int> boltdata = new List<int>(); for (int i = 0; i < data.Length; i++) { int boltIndex; int boltad; bool ret = UpdateBoltAD(data[i], (start_grid + i) * posOfGrid, direction, out boltIndex, out boltad); if (ret == true) { if (start_boltIndex == -1) start_boltIndex = boltIndex; boltdata.Add(boltad); } } if (boltdata.Count() == 0) { boltAD = null; return false; } start_boltIndex = GetInfoBoltIndex(start_boltIndex); while (start_boltIndex < 0 && boltdata.Count()>0) { boltdata.RemoveAt(0); start_boltIndex--; } while ((start_boltIndex + boltdata.Count() > nbolts) && boltdata.Count() > 0) { boltdata.RemoveAt(boltdata.Count() - 1); } boltAD = boltdata.ToArray(); if (boltAD.Count() > 0) return true; return false; } /// <summary> /// 转换总分区表 的序号 /// </summary> /// <param name="curr_boltindex">当前分区表的序号</param> /// <returns></returns> int GetInfoBoltIndex(int curr_boltindex) { int curr_boltno1st; IEnumerable<Range> curr_bolts; boltmap.GetBolts(out curr_boltno1st, out curr_bolts); int offset = curr_boltno1st - boltmap.FirstBoltNo; return curr_boltindex + offset; } } public class BoltMapHelper { IBoltMapBase boltmap; public BoltMapHelper(IBoltMapBase boltmap) { this.boltmap = boltmap; } public int[] Map(Misc.DIRECTION direction, int posBegin, int posOfGrid, int[] dat) { int boltno1st = boltmap.FirstBoltNo; int nbolts = boltmap.NBolts; int curr_boltno1st;//当前分区表 1st分区号 IEnumerable<Range> curr_bolts;//当前分区表 int curr_nbolts; boltmap.GetBolts(out curr_boltno1st, out curr_bolts); curr_nbolts = curr_bolts.Count(); int[] frame = new int[curr_nbolts]; int gridbegin = posBegin / posOfGrid; int len = dat.Length; for (int i = 0; i < curr_nbolts; i++) { int sum = 0; int cnt = 0; int total = 0; int j; int begin = curr_bolts.ElementAt(i).Begin; int end = curr_bolts.ElementAt(i).End; begin = boltmap.BoltExchange(direction, begin); end = boltmap.BoltExchange(direction, end); int begin_grid = begin / posOfGrid; int end_grid = end / posOfGrid; for (j = begin_grid; j <= end_grid; j++) { int index = j - gridbegin; if ((index >= 0) && (index < len)) { if (Misc.MyBase.ISVALIDATA(dat[index])) { sum += dat[index]; cnt++; } total++; } } //数据有效必须是 有效数据 多于 一个分区总数的 1/3 if (cnt > (total / 3)) { frame[i] = sum / cnt; } else { frame[i] = Misc.MyBase.NULL_VALUE; } } //数据平滑 int smooth = boltmap.Smooth; if (smooth < 0) smooth = 0; else if (smooth > 10) smooth = 10; int[] frame2; if (smooth > 0) { frame2 = new int[curr_nbolts]; for (int i = 0; i < curr_nbolts; i++) { int sum = 0; int cnt = 0; int index_b = i - smooth; int index_e = i + smooth; for (int j = index_b; j <= index_e; j++) { if ((j >= 0) && (j < curr_nbolts)) { if (Misc.MyBase.ISVALIDATA(frame[j])) { sum += frame[j]; cnt++; } } } if (cnt > 0) { frame2[i] = sum / cnt; } else { frame2[i] = Misc.MyBase.NULL_VALUE; } } } else { frame2 = frame; } frame = new int[nbolts]; int offset = curr_boltno1st - boltno1st; for (int i = 0; i < nbolts; i++) { if (i < offset) { frame[i] = Misc.MyBase.NULL_VALUE; } else if (i < offset + curr_nbolts) { frame[i] = frame2[i - offset]; } else { frame[i] = Misc.MyBase.NULL_VALUE; } } return frame; } #region 根据边界调整分区 public class ExChange { /// <summary> /// 平移 /// </summary> public int Offset { get; set; } /// <summary> /// 比例 /// </summary> public double Amp { get; set; } = 1; /// <summary> /// 初始化 /// </summary> public void Init() { Offset = 0; Amp = 1; } } public ExChange[] mExChange = new ExChange[2] { new ExChange(), new ExChange() }; public void InitExChange() { for (int i = 0; i < 2; i++) { ExChange exchange = mExChange[i]; exchange.Init(); } } public int PositionExchange(Misc.DIRECTION direction, int position) { int idx = 0; if (direction == Misc.DIRECTION.BACKWARD) idx = 1; ExChange exchange = mExChange[idx]; return (int)((position - exchange.Offset) / exchange.Amp); } public int BoltExchange(Misc.DIRECTION direction, int bolt_pos) { int idx = 0; if (direction == Misc.DIRECTION.BACKWARD) idx = 1; ExChange exchange = mExChange[idx]; return (int)(bolt_pos * exchange.Amp) + exchange.Offset; } #endregion } }