/// <summary> /// Проверить QR-угол на валидность /// </summary> /// <param name="TopLeftFinder"></param> /// <param name="TopRightFinder"></param> /// <param name="BottomLeftFinder"></param> /// <returns></returns> internal static Corner CreateCorner(Finder TopLeftFinder, Finder TopRightFinder, Finder BottomLeftFinder) { // Try all three possible permutation of three finders for (int Index = 0; Index < 3; Index++) { // TestCorner runs three times to test all posibilities rotate top left, top right and bottom left if (Index != 0) { Finder Temp = TopLeftFinder; TopLeftFinder = TopRightFinder; TopRightFinder = BottomLeftFinder; BottomLeftFinder = Temp; } // Top line slope Double TopLineDeltaX = TopRightFinder.Col - TopLeftFinder.Col; Double TopLineDeltaY = TopRightFinder.Row - TopLeftFinder.Row; // Left line slope Double LeftLineDeltaX = BottomLeftFinder.Col - TopLeftFinder.Col; Double LeftLineDeltaY = BottomLeftFinder.Row - TopLeftFinder.Row; // Top line length Double TopLineLength = Math.Sqrt(TopLineDeltaX * TopLineDeltaX + TopLineDeltaY * TopLineDeltaY); // Left line length Double LeftLineLength = Math.Sqrt(LeftLineDeltaX * LeftLineDeltaX + LeftLineDeltaY * LeftLineDeltaY); // The short side must be at least 80% of the long side if (Math.Min(TopLineLength, LeftLineLength) < QRDecoder.CORNER_SIDE_LENGTH_DEV * Math.Max(TopLineLength, LeftLineLength)) { continue; } // Top line vector Double TopLineSin = TopLineDeltaY / TopLineLength; Double TopLineCos = TopLineDeltaX / TopLineLength; // Rotate lines such that top line is parallel to x axis left line after rotation Double NewLeftX = TopLineCos * LeftLineDeltaX + TopLineSin * LeftLineDeltaY; Double NewLeftY = -TopLineSin * LeftLineDeltaX + TopLineCos * LeftLineDeltaY; // New left line X should be zero (or between +/- 4 deg) if (Math.Abs(NewLeftX / LeftLineLength) > QRDecoder.CORNER_RIGHT_ANGLE_DEV) { continue; } // Swap top line with left line if (NewLeftY < 0) { // Swap top left with bottom right Finder TempFinder = TopRightFinder; TopRightFinder = BottomLeftFinder; BottomLeftFinder = TempFinder; } return(new Corner(TopLeftFinder, TopRightFinder, BottomLeftFinder)); } return(null); }
/// <summary> /// Горизонтальное и вертикальное сканирование перекрываются /// </summary> internal bool Overlap(Finder Other) { return(Other.Col1 < Col2 && Other.Col2 >= Col1 && Other.Row1 < Row2 && Other.Row2 >= Row1); }