BorderSearch.cs 26.2 KB
Newer Older
潘栩锋's avatar
潘栩锋 committed
1 2 3 4 5 6 7 8
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Misc;
using FLY.Thick.Base.Common;
using FLY.Thick.Base.IService;
9
using FObjBase;
潘栩锋's avatar
潘栩锋 committed
10 11 12 13 14 15 16 17 18

namespace FLY.Thick.Base.Server
{

    /// <summary>
    /// 边界查找
    /// </summary>
    public class BorderSearch : IBorderSearchService, INotifyPropertyChanged, Misc.ISaveToXml
    {
19 20 21
        /// <summary>
        /// 报警测试
        /// </summary>
22
        //public static FLY.OBJComponents.Common.ERRNO BORDER_ERRNO_NOFILM = new FLY.OBJComponents.Common.ERRNO() { Code = 50, Descrption = "边界异常,没有被测物" };
23

潘栩锋's avatar
潘栩锋 committed
24 25 26 27 28 29 30 31
        #region 延时执行,Markno
        public const int MARKNO_SAVE = 1;
        #endregion
        #region 属性,成员变量的代理

        /// <summary>
        /// 启动与否
        /// </summary>
潘栩锋's avatar
1  
潘栩锋 committed
32 33
        public bool Enable { get; set; }

潘栩锋's avatar
潘栩锋 committed
34 35 36
        /// <summary>
        /// 边界拐点检测,找到的边界更加精确
        /// </summary>
潘栩锋's avatar
1  
潘栩锋 committed
37
        public bool IsBreakDetect { get; set; } = true;
潘栩锋's avatar
潘栩锋 committed
38

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
        /// <summary>
        /// 边界
        /// </summary>
        protected class BorderWithOk 
        {
            /// <summary>
            ///  边界值
            /// </summary>
            public Range value = new Range();
            /// <summary>
            /// 开始边界100%可靠
            /// </summary>
            public bool isBeginOk;
            /// <summary>
            /// 结束边界100%可靠
            /// </summary>
            public bool isEndOk;
            /// <summary>
            /// 真实可靠的边界值
            /// </summary>
            public Range real = new Range();

            public void UpdateReal(int sensorWidth, int expect, int mid, bool isBeginOk, bool isEndOk) {
                if (value.IsValid)
                {
                    real.Begin = value.Begin + sensorWidth / 2;
                    real.End = value.End - sensorWidth / 2;

                    //修正!!!
                    if (real.Width < expect)
                    {
                        if (isBeginOk && isEndOk)
                        {

                        }
                        else if (isBeginOk)
                        {
                            real.End = real.Begin + expect;
                        }
                        else if (isEndOk)
                        {
                            real.Begin = real.End - expect;
                        }
                        else //开始边界与结束边界都是假的
                        {
                            //居中处理
                            real.Begin = mid - expect / 2;
                            real.End = real.Begin + expect;
                        }
                    }
                }
            }

            public void UpdateReal(int sensorWidth, int expect, int mid)
            {
                UpdateReal(sensorWidth, expect, mid, isBeginOk, isEndOk);
            }
            public void UpdateReal(int sensorWidth )
            {
                if (value.IsValid)
                {
                    real.Begin = value.Begin + sensorWidth / 2;
                    real.End = value.End - sensorWidth / 2;
                }
            }
        }
105 106 107
        /// <summary>
        /// 正反向边界数据
        /// </summary>
108
        protected BorderWithOk[] borders = new BorderWithOk[2] { new BorderWithOk(), new BorderWithOk() };
潘栩锋's avatar
潘栩锋 committed
109 110 111 112

        /// <summary>
        /// 有限范围
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
113 114
        [PropertyChanged.DoNotCheckEquality]
        public Range Valid { get; set; } = new Range();
潘栩锋's avatar
潘栩锋 committed
115 116 117
        /// <summary>
        /// 边界
        /// </summary>
118
        public Range Border_Forw { get { return borders[0].value; } }
潘栩锋's avatar
1  
潘栩锋 committed
119 120 121
        /// <summary>
        /// 边界
        /// </summary>
122
        public Range Border_Backw { get { return borders[1].value; } }
潘栩锋's avatar
1  
潘栩锋 committed
123 124 125 126

        /// <summary>
        /// 膜范围
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
127
        public Range Border { get; set; } = new Range();
潘栩锋's avatar
1  
潘栩锋 committed
128

潘栩锋's avatar
潘栩锋 committed
129 130 131
        /// <summary>
        /// 当前膜宽,测量出来的,单位是 脉冲
        /// </summary>
潘栩锋's avatar
1  
潘栩锋 committed
132 133
        public int Width { get; protected set; }

潘栩锋's avatar
潘栩锋 committed
134 135 136
        /// <summary>
        /// 膜中间位置 单位 脉冲
        /// </summary>
潘栩锋's avatar
1  
潘栩锋 committed
137
        public int Mid { get; protected set; }
潘栩锋's avatar
潘栩锋 committed
138
        
潘栩锋's avatar
潘栩锋 committed
139 140 141
        /// <summary>
        /// 手动设置温修AD值
        /// </summary>
潘栩锋's avatar
1  
潘栩锋 committed
142
        public bool TempADBySet { get; set; }
潘栩锋's avatar
潘栩锋 committed
143 144 145 146

        /// <summary>
        /// 温修AD值
        /// </summary>
潘栩锋's avatar
1  
潘栩锋 committed
147 148
        public int CurrTempAD { get; set; } = 50000;

潘栩锋's avatar
潘栩锋 committed
149 150 151
        /// <summary>
        /// 温修AD值
        /// </summary>
潘栩锋's avatar
1  
潘栩锋 committed
152 153
        public int TempAD { get; set; } = 50000;

潘栩锋's avatar
潘栩锋 committed
154 155 156
        /// <summary>
        /// AD超过了范围, 就认为开始找到边界
        /// </summary>
157 158 159 160 161 162 163 164 165 166 167
        public int TempRange { get; set; } = 1000;

        /// <summary>
        /// 温修范围是温修的百分比
        /// </summary>
        public bool IsTempRangeByPercent { get; set; } = true;

        /// <summary>
        ///  温修范围百分比
        /// </summary>
        public double TempRangePercent { get; set; } = 0.02;
潘栩锋's avatar
1  
潘栩锋 committed
168 169


潘栩锋's avatar
潘栩锋 committed
170 171 172
        /// <summary>
        /// 有滤波器,只有非空的连续N个pos以上,才开始算边界开始
        /// </summary>
潘栩锋's avatar
1  
潘栩锋 committed
173
        public int N { get; set; }
潘栩锋's avatar
潘栩锋 committed
174 175 176 177

        /// <summary>
        /// 探头直径,单位脉冲, 膜宽 = 边界范围 - 探头直径
        /// </summary>
潘栩锋's avatar
1  
潘栩锋 committed
178 179
        public int SensorWidth { get; set; }

潘栩锋's avatar
潘栩锋 committed
180 181 182 183 184 185



        /// <summary>
        /// 找到边界后,再往内缩N2个脉冲,防止边界找得不准的问题。
        /// </summary>
潘栩锋's avatar
1  
潘栩锋 committed
186 187
        public int N2 { get; set; }

潘栩锋's avatar
潘栩锋 committed
188 189 190 191

        /// <summary>
        /// 记录两个边界以后扫描,以它们再外扩N3个脉冲,作为扫描范围 
        /// </summary>
潘栩锋's avatar
1  
潘栩锋 committed
192 193
        public int N3 { get; set; }

潘栩锋's avatar
潘栩锋 committed
194
        /// <summary>
195
        /// 数据更新时间
潘栩锋's avatar
潘栩锋 committed
196
        /// </summary>
197
        public DateTime UpdateTime { get; protected set; }
潘栩锋's avatar
潘栩锋 committed
198

199 200 201 202 203 204
        /// <summary>
        /// 产品宽度,设置值 单位:脉冲
        /// 当膜超过范围(没有经过阀值),就使用它,猜边界在哪
        /// </summary>
        public int ProductWidth { get; protected set; }

潘栩锋's avatar
潘栩锋 committed
205 206
        #endregion

207
        OBJComponents.Server.WarningSystem warningSystem;
208 209 210 211 212 213 214


        /// <summary>
        /// 用于调试, 进入到边界查找的数据
        /// </summary>
        protected BorderSearchGetViewReponse getViewReponse;

潘栩锋's avatar
潘栩锋 committed
215 216 217 218 219
        private string param_path = "bordersearch.xml";
        public BorderSearch()
        {
            Default();
            this.PropertyChanged += new PropertyChangedEventHandler(BorderSearch_PropertyChanged);
潘栩锋's avatar
潘栩锋 committed
220 221


潘栩锋's avatar
潘栩锋 committed
222 223 224 225 226 227 228 229
        }

        public BorderSearch(string param_path) 
        {
            if (!string.IsNullOrEmpty(param_path))
                this.param_path = param_path;
            Default();
            this.PropertyChanged += new PropertyChangedEventHandler(BorderSearch_PropertyChanged);
潘栩锋's avatar
潘栩锋 committed
230 231 232 233 234 235 236 237 238 239

            this.Border_Forw.PropertyChanged += (s, e) => {
                NotifyPropertyChanged("Border_Forw");
            };
            this.Border_Backw.PropertyChanged += (s, e) => {
                NotifyPropertyChanged("Border_Backw");
            };
            this.Border.PropertyChanged += (s, e) => {
                NotifyPropertyChanged("Border");
            };
潘栩锋's avatar
潘栩锋 committed
240 241
            Load();
        }
242 243 244 245 246

        public void Init(OBJComponents.Server.WarningSystem warningSystem) 
        {
            this.warningSystem = warningSystem;
        }
潘栩锋's avatar
潘栩锋 committed
247 248 249
        void Default() 
        {
            Enable = false;
潘栩锋's avatar
潘栩锋 committed
250 251
            Valid = new Range() { Begin = 1200, End = 7400 };
            
潘栩锋's avatar
潘栩锋 committed
252 253 254 255 256 257 258 259
            Init();

            TempAD = -1;
            N = 20;
            N2 = 400;
            N3 = 1000;
            SensorWidth = 250;
            Width = 0;
潘栩锋's avatar
潘栩锋 committed
260 261 262
            Border_Backw.Reset();
            Border_Forw.Reset();
            Border.Reset();
潘栩锋's avatar
潘栩锋 committed
263 264
            Mid = Valid.Mid;
            TempRange = 500;
265 266
            TempRangePercent = 500.0 / 50000;
            IsTempRangeByPercent = true;
267
            UpdateTime = DateTime.MinValue;
潘栩锋's avatar
潘栩锋 committed
268 269 270
        }


潘栩锋's avatar
潘栩锋 committed
271

潘栩锋's avatar
潘栩锋 committed
272 273 274

        void BorderSearch_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
275
            if (e.PropertyName == "CurrTempAD")
潘栩锋's avatar
潘栩锋 committed
276 277 278 279
            {
                if (!TempADBySet)
                    TempAD = CurrTempAD;
            }
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
            else if (e.PropertyName == "TempAD")
            {
                if (IsTempRangeByPercent)
                {
                    TempRange = (int)(TempAD * TempRangePercent);
                }
            }
            else if ((e.PropertyName == "TempRangePercent") || (e.PropertyName == "IsTempRangeByPercent"))
            {
                if (IsTempRangeByPercent)
                {
                    TempRange = (int)(TempAD * TempRangePercent);
                }
            }

潘栩锋's avatar
潘栩锋 committed
295 296 297 298
        }

        public void Init()
        {
潘栩锋's avatar
潘栩锋 committed
299 300
            Border_Backw.Reset();
            Border_Forw.Reset();
潘栩锋's avatar
潘栩锋 committed
301
            Width = 0;
潘栩锋's avatar
潘栩锋 committed
302
            Border.Reset();
潘栩锋's avatar
潘栩锋 committed
303 304
            Mid = Valid.Mid;
        }
305 306 307 308 309 310 311 312 313


        public void SetProductWidth(int productWidth) {
            ProductWidth = productWidth;
        }
        /// <summary>
        /// 获取扫描范围
        /// </summary>
        /// <returns></returns>
潘栩锋's avatar
潘栩锋 committed
314 315
        public Range GetScanRange() 
        {
316
            GetScanRange(out int b, out int e);
潘栩锋's avatar
潘栩锋 committed
317 318
            return new Range() { Begin = b, End = e };
        }
319 320 321 322 323
        /// <summary>
        /// 获取扫描范围
        /// </summary>
        /// <param name="posBegin"></param>
        /// <param name="posEnd"></param>
潘栩锋's avatar
潘栩锋 committed
324 325 326
        public void GetScanRange(out int posBegin, out int posEnd)
        {

327
            int min, max;
潘栩锋's avatar
潘栩锋 committed
328

329
            if (borders.All(b => b.value.IsValid))
潘栩锋's avatar
潘栩锋 committed
330
            {
331 332
                min = borders.Min(b => b.value.Begin) - N3;
                max = borders.Max(b => b.value.End) + N3;
潘栩锋's avatar
潘栩锋 committed
333
            }
334
            else if (borders[0].value.IsValid)
潘栩锋's avatar
潘栩锋 committed
335
            {
336 337
                min = borders[0].value.Begin - N3;
                max = borders[0].value.End + N3;
潘栩锋's avatar
潘栩锋 committed
338
            }
339
            else if (borders[1].value.IsValid)
潘栩锋's avatar
潘栩锋 committed
340
            {
341 342
                min = borders[1].value.Begin - N3;
                max = borders[1].value.End + N3;
潘栩锋's avatar
潘栩锋 committed
343
            }
344
            else 
潘栩锋's avatar
潘栩锋 committed
345
            {
346
                //都不能找到边界
潘栩锋's avatar
1  
潘栩锋 committed
347 348
                min = Valid.Begin;
                max = Valid.End;
潘栩锋's avatar
潘栩锋 committed
349
            }
350 351 352 353

            //范围限制
            posBegin = Math.Max(min, Valid.Begin);
            posEnd = Math.Min(max, Valid.End);
潘栩锋's avatar
潘栩锋 committed
354 355 356 357
        }



358

潘栩锋's avatar
潘栩锋 committed
359 360 361
        /// <summary>
        /// 初略操作,超过范围 就是边界
        /// </summary>
362 363 364 365 366 367 368
        /// <param name="dat">全部数据</param>
        /// <param name="validBegin_grid">有效范围开始</param>
        /// <param name="validEnd_grid">有效范围结束</param>
        /// <param name="borderBegin_grid">输出的开始边界</param>
        /// <param name="borderEnd_grid">输出的结束边界</param>
        /// <param name="isBorderBeginOk">开始边界经过阀值线</param>
        /// <param name="isBorderEndOk">结束边界经过阀值线</param>
潘栩锋's avatar
潘栩锋 committed
369
        /// <returns></returns>
370 371 372 373 374 375 376 377
        protected bool FindFilm_Threshold(
            int[] dat, 
            int validBegin_grid,
            int validEnd_grid, 
            out int borderBegin_grid,
            out int borderEnd_grid, 
            out bool isBorderBeginOk, 
            out bool isBorderEndOk) 
潘栩锋's avatar
潘栩锋 committed
378
        {
379 380 381 382 383
            borderBegin_grid = -1;
            borderEnd_grid = -1;
            isBorderBeginOk = false;
            isBorderEndOk = false;
            int mid_grid = (validBegin_grid + validEnd_grid) / 2;
潘栩锋's avatar
潘栩锋 committed
384 385 386

            //从中间开始向左边找
            //必须先找到膜
387
            for (int i = mid_grid; i >= validBegin_grid; i--)
潘栩锋's avatar
潘栩锋 committed
388 389 390 391 392 393 394 395
            {
                if (i >= 0 && i < dat.Length)
                {
                    if (Misc.MyBase.ISVALIDATA(dat[i]))
                    {
                        if (Math.Abs(TempAD - dat[i]) > TempRange)
                        {
                            //膜
396
                            borderBegin_grid = i;
潘栩锋's avatar
潘栩锋 committed
397 398 399 400
                        }
                        else
                        {
                            //空气
401
                            if (borderBegin_grid != -1)
潘栩锋's avatar
潘栩锋 committed
402
                            {
403
                                isBorderBeginOk = true;
潘栩锋's avatar
潘栩锋 committed
404 405 406 407 408 409 410 411 412 413 414 415
                                //之前有膜
                                break;
                            }
                        }
                    }
                }
                else if (i < 0)
                {
                    break;
                }
            }

416
            if (borderBegin_grid == -1)//没有膜
潘栩锋's avatar
潘栩锋 committed
417 418 419
            {
                //从左边开始找
                //找左边界 ,找阀值点
420
                for (int i = mid_grid; i <= validEnd_grid; i++)
潘栩锋's avatar
潘栩锋 committed
421 422 423 424 425 426 427 428
                {
                    if (i >= 0 && i < dat.Length)
                    {
                        if (Misc.MyBase.ISVALIDATA(dat[i]))
                        {
                            if (Math.Abs(TempAD - dat[i]) > TempRange)
                            {
                                //膜
429 430
                                borderBegin_grid = i;
                                isBorderBeginOk = true;
潘栩锋's avatar
潘栩锋 committed
431 432 433 434 435
                                break;
                            }
                        }
                    }
                }
436
                if (borderBegin_grid == -1)//没有膜
潘栩锋's avatar
潘栩锋 committed
437 438 439 440
                    return false;
            }
            
            //从左边界开始找
441
            for (int i = borderBegin_grid; i <= validEnd_grid; i++)
潘栩锋's avatar
潘栩锋 committed
442 443 444 445 446 447 448 449
            {
                if (i >= 0 && i < dat.Length)
                {
                    if (Misc.MyBase.ISVALIDATA(dat[i]))
                    {
                        if (Math.Abs(TempAD - dat[i]) > TempRange)
                        {
                            //膜
450
                            borderEnd_grid = i;
潘栩锋's avatar
潘栩锋 committed
451 452 453 454
                        }
                        else
                        {
                            //空气
455
                            if (borderEnd_grid != -1)
潘栩锋's avatar
潘栩锋 committed
456
                            {
457
                                isBorderEndOk = true;
潘栩锋's avatar
潘栩锋 committed
458 459 460 461 462 463 464 465
                                //之前有膜
                                break;
                            }
                        }
                    }
                }
            }

466
            if (borderEnd_grid == -1)//没有膜
潘栩锋's avatar
潘栩锋 committed
467 468 469 470 471 472 473 474
                return false;

            return true;
        }
        /// <summary>
        /// 精细操作,再向外找 折点
        /// </summary>
        /// <param name="dat"></param>
475 476
        /// <param name="sensor_grid">探头直径</param>
        /// <param name="filter_grid">滤波</param>
潘栩锋's avatar
潘栩锋 committed
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
        /// <param name="borderbegin_grid"></param>
        /// <param name="borderend_grid"></param>
        /// <returns></returns>
        bool FindFilm_Break(int[] dat, int sensor_grid, int filter_grid, ref int borderbegin_grid, ref int borderend_grid)
        {
            //当前肯定在斜波上
            //边界肯定在 粗边界以外 探头半径 内
            //int N4 = SensorWidth / posOfGrid;

            if (sensor_grid <= 2)
            {
                //不用找,传感器直径非常小,已经很准确了
                return true;
            }

            //int num = N / posOfGrid / 2;//滤波半径
            int num = filter_grid / 2;
            if (num < 1) num = 1;


            int[] filterdats = new int[dat.Length];//数据滤波
498
            for (int i = 0; i < dat.Length; i++)
潘栩锋's avatar
潘栩锋 committed
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
            {
                int b = i - num;
                int e = i + num;
                if (b < 0)
                {
                    b = 0;
                    e = b + num * 2;
                }
                else if (e >= (dat.Length - 1))
                {
                    e = dat.Length - 1;
                    b = e - num * 2;
                }
                filterdats[i] = Misc.MyMath.Avg(dat, b, e);
            }
514 515
            int bg = borderbegin_grid;
            int eg = borderend_grid;
潘栩锋's avatar
潘栩锋 committed
516

517 518 519 520
            int[] breakdats = new int[dat.Length];
            num = 1;

            for (int i = 0; i < dat.Length; i++)
潘栩锋's avatar
潘栩锋 committed
521
            {
522 523 524 525 526 527 528 529 530 531 532
                if ((i - num) < 0)
                    breakdats[i] = Misc.MyBase.NULL_VALUE;
                else if ((i + num) >= dat.Length)
                    breakdats[i] = Misc.MyBase.NULL_VALUE;
                else if (!Misc.MyBase.ISVALIDATA(filterdats[i - num]))
                    breakdats[i] = Misc.MyBase.NULL_VALUE;
                else if (!Misc.MyBase.ISVALIDATA(filterdats[i + num]))
                    breakdats[i] = Misc.MyBase.NULL_VALUE;
                else if (!Misc.MyBase.ISVALIDATA(filterdats[i]))
                    breakdats[i] = Misc.MyBase.NULL_VALUE;
                else
潘栩锋's avatar
潘栩锋 committed
533
                {
534
                    breakdats[i] = Math.Abs((filterdats[i] - filterdats[i - num]) * (filterdats[i + num] - filterdats[i]));
潘栩锋's avatar
潘栩锋 committed
535 536 537
                }
            }

538
            bool isdown = false;
潘栩锋's avatar
潘栩锋 committed
539 540 541 542 543 544 545
            //从第1次找到的边界开始,往外找,找折点的最小值
            for (int i = borderbegin_grid; i >= (borderbegin_grid - sensor_grid); i--)
            {
                if ((i - num) < 0)
                    break;
                if ((i + num) >= dat.Length)
                    break;
546
                if (!Misc.MyBase.ISVALIDATA(breakdats[i - num]))
潘栩锋's avatar
潘栩锋 committed
547
                    break;
548
                if (!Misc.MyBase.ISVALIDATA(breakdats[i + num]))
潘栩锋's avatar
潘栩锋 committed
549
                    break;
550
                if (!Misc.MyBase.ISVALIDATA(breakdats[i]))
潘栩锋's avatar
潘栩锋 committed
551
                    break;
552 553 554 555 556 557 558 559 560 561 562 563 564
                if (breakdats[i] < breakdats[i + num])
                {
                    //在减少
                    bg = i;
                    isdown = true;
                }
                if (isdown)
                {
                    if (breakdats[i] < breakdats[i - num])
                    {
                        //之前那个就是最小值
                        break;
                    }
潘栩锋's avatar
潘栩锋 committed
565 566
                }
            }
567
            isdown = false;
潘栩锋's avatar
潘栩锋 committed
568 569 570 571 572 573 574 575 576 577 578 579 580
            for (int i = borderend_grid; i <= (borderend_grid + sensor_grid); i++)
            {
                if ((i - num) < 0)
                    break;
                if ((i + num) >= dat.Length)
                    break;
                if (!Misc.MyBase.ISVALIDATA(filterdats[i - num]))
                    break;
                if (!Misc.MyBase.ISVALIDATA(filterdats[i + num]))
                    break;
                if (!Misc.MyBase.ISVALIDATA(filterdats[i]))
                    break;

581
                if (breakdats[i] < breakdats[i - num])
潘栩锋's avatar
潘栩锋 committed
582
                {
583 584 585 586 587 588 589 590 591 592 593
                    //在减少
                    eg = i;
                    isdown = true;
                }
                if (isdown)
                {
                    if (breakdats[i] < breakdats[i + num])
                    {
                        //之前那个就是最小值
                        break;
                    }
潘栩锋's avatar
潘栩锋 committed
594 595 596 597 598 599
                }
            }
            borderbegin_grid = bg;
            borderend_grid = eg;
            return true;
        }
600

潘栩锋's avatar
潘栩锋 committed
601 602 603 604 605 606 607 608 609 610 611
        /// <summary>
        /// 放入grid数据,分析边界
        /// </summary>
        /// <param name="direction"></param>
        /// <param name="posOfGrid"></param>
        /// <param name="gridBegin"></param>
        /// <param name="dat"></param>
        /// <returns></returns>
        public virtual bool FindFilm(DIRECTION direction, int posOfGrid, int gridBegin, int[] dat)
        {
            //把数据记录下来
612
            getViewReponse = new BorderSearchGetViewReponse()
潘栩锋's avatar
潘栩锋 committed
613
            {
614 615 616 617 618 619
                direction = direction,
                posOfGrid = posOfGrid,
                gridBegin = gridBegin,
                dat = dat
            };
            UpdateTime = DateTime.Now;
潘栩锋's avatar
潘栩锋 committed
620 621 622 623 624

            //转为 dat 的序号
            int validbegin_grid = Valid.Begin / posOfGrid - gridBegin;
            int validend_grid = Valid.End / posOfGrid - gridBegin;

625 626 627 628
            if (!FindFilm_Threshold(dat, 
                validbegin_grid, validend_grid, 
                out int borderbegin_grid, out int borderend_grid, 
                out bool isBorderBeginOk, out bool isBorderEndOk))
629
            {
630
                //warningSystem.Add(BORDER_ERRNO_NOFILM.Code, BORDER_ERRNO_NOFILM.Descrption, OBJComponents.Common.ERR_STATE.ON);
潘栩锋's avatar
潘栩锋 committed
631
                return false;
632
            }
633
            else {
634
                //warningSystem.Add(BORDER_ERRNO_NOFILM.Code, BORDER_ERRNO_NOFILM.Descrption, OBJComponents.Common.ERR_STATE.OFF);
635
            }
潘栩锋's avatar
潘栩锋 committed
636 637 638 639 640 641 642 643 644 645 646 647 648 649
            //N2 只是用来判断一下膜够不够宽而已,没用
            int N2_grid = (N2*3+SensorWidth) / posOfGrid;
            
            if ((borderend_grid - borderbegin_grid) < N2_grid)//膜太短
                return false;

            if (IsBreakDetect)
            {
                int sensor_grid = SensorWidth / posOfGrid;
                int filter_grid = N / posOfGrid;
                //精细查找
                FindFilm_Break(dat, sensor_grid, filter_grid, ref borderbegin_grid, ref borderend_grid);
            }

650
            int idx = (direction == DIRECTION.FORWARD) ? 0 : 1;
651
            var border = borders[idx];
652

潘栩锋's avatar
潘栩锋 committed
653
            //转为 脉冲
654 655 656 657 658 659
            border.value.Begin = (borderbegin_grid + gridBegin) * posOfGrid;
            border.value.End = (borderend_grid +gridBegin) * posOfGrid;
            border.isBeginOk = isBorderBeginOk;
            border.isEndOk = isBorderEndOk;

            getViewReponse.border = border.value;
潘栩锋's avatar
潘栩锋 committed
660

661
            if (borders.All(b => b.value.IsValid))
潘栩锋's avatar
潘栩锋 committed
662
            {
663 664 665 666 667 668
                foreach(var bo in borders)
                    bo.UpdateReal(SensorWidth, ProductWidth, Valid.Mid, 
                        borders.All(b=>b.isBeginOk), borders.All(b => b.isEndOk));

                Border.Begin = (int)borders.Average(b => b.real.Begin);
                Border.End = (int)borders.Average(b => b.real.End);
潘栩锋's avatar
潘栩锋 committed
669
            }
670
            else if (border.value.IsValid)
潘栩锋's avatar
潘栩锋 committed
671
            {
672 673 674 675
                foreach (var bo in borders)
                    bo.UpdateReal(SensorWidth, ProductWidth, Valid.Mid);

                Border.Copy(border.real);
潘栩锋's avatar
潘栩锋 committed
676
            }
677 678
            Width = Border.Width;
            Mid = Border.Mid;
潘栩锋's avatar
潘栩锋 committed
679 680 681 682 683 684 685 686 687 688 689 690
            return true;
        }
        
        /// <summary>
        /// 获取膜边界,当根本找不到膜时,返回找边界范围!!!
        /// 膜的边界,只是斜波的中间而已。
        /// </summary>
        /// <param name="direction"></param>
        /// <param name="posBegin"></param>
        /// <param name="posEnd"></param>
        public void GetBorder(DIRECTION direction, out int posBegin, out int posEnd) 
        {
691 692 693
            int idx = (direction == DIRECTION.FORWARD) ? 0 : 1;
            var border = borders[idx];
            if (border.value.IsValid)
潘栩锋's avatar
潘栩锋 committed
694
            {
695 696
                posBegin = border.real.Begin;
                posEnd = border.real.End;
潘栩锋's avatar
潘栩锋 committed
697
            }
698
            else
潘栩锋's avatar
潘栩锋 committed
699
            {
700 701 702 703 704
                idx += 1;
                if (idx > 1)
                    idx = 0;
                border = borders[idx];
                if (border.value.IsValid)
潘栩锋's avatar
潘栩锋 committed
705
                {
706 707 708 709 710 711
                    posBegin = border.real.Begin;
                    posEnd = border.real.End;
                }
                else {
                    posBegin = Misc.MyBase.NULL_VALUE;
                    posEnd = Misc.MyBase.NULL_VALUE;
潘栩锋's avatar
潘栩锋 committed
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754
                }
            }
        }
        /// <summary>
        /// 获取膜边界,当根本找不到膜时,返回IsVaild=false 的Range!!!
        /// 膜的边界,只是斜波的中间而已。
        /// </summary>
        /// <param name="direction"></param>
        /// <returns></returns>
        public Range GetBorder(DIRECTION direction) 
        {
            int b, e;
            GetBorder(direction, out b, out e);
            return new Range() { Begin = b, End = e };
        }
        
        /// <summary>
        /// 获取 膜边界 向内缩 N2 + SensorWidth / 2
        /// </summary>
        /// <param name="direction"></param>
        /// <param name="posBegin"></param>
        /// <param name="posEnd"></param>
        public void GetBoltRange(DIRECTION direction, out int posBegin, out int posEnd) 
        {
            GetBorder(direction, out posBegin, out posEnd);
            if (Misc.MyBase.ISVALIDATA(posBegin)) 
            {
                posBegin += (SensorWidth / 2 + N2);
                posEnd -= (SensorWidth / 2 + N2);
            }
        }
        /// <summary>
        /// 膜边界 向内缩 N2 + SensorWidth / 2
        /// </summary>
        /// <param name="direction"></param>
        /// <returns></returns>
        public Range GetBoltRange(DIRECTION direction) 
        {
            int b, e;
            GetBoltRange(direction, out b, out e);
            return new Range() { Begin = b, End = e };
        }

755 756 757 758 759 760 761 762 763 764 765 766
        /// <summary>
        /// 获取混合后的横向数据;没有把横向留白剔除;只把纵向留白剔除。
        /// 数据单位 mm
        /// </summary>
        /// <param name="asyncDelegate"></param>
        /// <param name="asyncContext"></param>
        [AsyncCb(typeof(BorderSearchGetViewReponse))]
        public void GetView(AsyncCBHandler asyncDelegate, object asyncContext) 
        {
            asyncDelegate?.Invoke(asyncContext, getViewReponse);
        }

潘栩锋's avatar
潘栩锋 committed
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
        public bool Load() 
        {
            return Misc.SaveToXmlHepler.Load(param_path, this);
        }
        public bool Save() 
        {
            return Misc.SaveToXmlHepler.Save(param_path, this);
        }

        public void Apply() 
        {
            Save();
        }
        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));
            }
        }

        #endregion

        #region ISaveToXml 成员

        public string[] GetSavePropertyNames()
        {
            return new string[]{
                "Enable",
                "Valid",
                "TempADBySet",
                "TempAD",
                "TempRange",
803 804
                "TempRangePercent",
                "IsTempRangeByPercent",
潘栩锋's avatar
潘栩锋 committed
805 806 807 808 809 810 811 812 813 814 815
                "N",
                "SensorWidth",
                "N2",
                "N3",
                "IsBreakDetect"
            };
        }

        #endregion
    }
}