public void BoundsTest() { EulerMonomap2D euler = new EulerMonomap2D("30,30,30,30,30,30,30,30,30,30,30,30,30,30,30"); var hashCode = euler.GetHashCode(); Assert.IsTrue(true); }
public void NotEqualHashsTest() { EulerMonomap2D euler1 = new EulerMonomap2D("1,0,1,0,1,0,1,0,1,0,1,0,1,0,1"); EulerMonomap2D euler2 = new EulerMonomap2D("0,1,0,1,0,1,0,1,0,1,0,1,0,1,0"); Assert.AreNotEqual(euler1.GetHashCode(), euler2.GetHashCode()); }
/// <summary> /// Создание экземпляра класса <see cref="SymbolCode"/>. /// </summary> public SymbolCode(int height, EulerMonomap2D eulerCode) { if (height <= 0) { throw new ArgumentException(nameof(height)); } EulerCode = eulerCode; Height = height; }
private bool TryIntelliRecognition( Symbol possibleSymbol, EulerMonomap2D currentCharEuler, int height, out QChar @char) { @char = null; // TODO дорогое вычисление, пока тестовый вариант /* * Анализировать: * 1. Equals * 2. -1 < X < 1 * 3. Количество совпадений в базе знаний что бы не опираться на косячный шрифт. */ var possibleSybols = possibleSymbol.Codes.Select( code => { int rounding, equals; _comparer.Compare(code.EulerCode, currentCharEuler, out rounding, out equals); return(new { EulerEquals = equals, EulerRounding = rounding }); }) // TODO Как минимум половина набора совпадает (Стоит играться) .Where(result => result.EulerEquals >= _comparer.RoundingLimit).ToArray(); if (!possibleSybols.Any()) { return(false); } var bestValue = possibleSybols[0]; foreach (var possibleSybol in possibleSybols) { if (possibleSybol.EulerRounding > bestValue.EulerRounding) { bestValue = possibleSybol; } } @char = new QChar(possibleSymbol.Chr, QState.Assumptions, bestValue.EulerEquals, bestValue.EulerRounding, possibleSybols.Length); return(true); }
/// <inheritdoc/> void IEulerComparer.Compare(EulerMonomap2D euler1, EulerMonomap2D euler2, out int rounding, out int equals) { // Количество очень близких значений в интервале rounding = 0; // Количество полных совпадений equals = 0; ComputeDiff(euler1.S0, euler2.S0, ref rounding, ref equals); ComputeDiff(euler1.S1, euler2.S1, ref rounding, ref equals); ComputeDiff(euler1.S2, euler2.S2, ref rounding, ref equals); ComputeDiff(euler1.S3, euler2.S3, ref rounding, ref equals); ComputeDiff(euler1.S4, euler2.S4, ref rounding, ref equals); ComputeDiff(euler1.S5, euler2.S5, ref rounding, ref equals); ComputeDiff(euler1.S6, euler2.S6, ref rounding, ref equals); ComputeDiff(euler1.S7, euler2.S7, ref rounding, ref equals); ComputeDiff(euler1.S8, euler2.S8, ref rounding, ref equals); ComputeDiff(euler1.S9, euler2.S9, ref rounding, ref equals); ComputeDiff(euler1.S10, euler2.S10, ref rounding, ref equals); ComputeDiff(euler1.S11, euler2.S11, ref rounding, ref equals); ComputeDiff(euler1.S12, euler2.S12, ref rounding, ref equals); ComputeDiff(euler1.S13, euler2.S13, ref rounding, ref equals); ComputeDiff(euler1.S14, euler2.S14, ref rounding, ref equals); }
/// <summary> /// Создание экземпляра класса <see cref="QSymbol"/>. /// </summary> public QSymbol(IMonomap monomap, Point startPoint, EulerMonomap2D euler) { Euler = euler; Monomap = monomap; StartPoint = startPoint; }
/// <inheritdoc/> public QAnalyzedSymbol AnalyzeFragment( QSymbol currentFragment, IEnumerable <QSymbol> unknownFragments, IProducerConsumerCollection <QAnalyzedSymbol> recognizedSymbols) { /* * Алгоритм работы. * P.S. Мы работаем со 100% не известным символом, либо фрагментом символа. * * * Input1: ip * Input2: Red Alert * сначала будет R потом A затем l. * e, d будут подмяты затем на e, r будет сплющивание вектора * * Input3: iiа результат при анализе ii они сольются */ // TODO Позже к высоте можно привязываться const int DefaultSplitStep = 3; var currentFragmentMinVector = currentFragment.StartPoint.Y + DefaultSplitStep; // Распознанные символы, лежащие в диапазоне поиска var currentLineRecognizedChars = recognizedSymbols.Where( symbol => symbol.StartPoint.Y <= currentFragmentMinVector && currentFragmentMinVector <= symbol.StartPoint.Y + symbol.Height).ToArray(); Point bottomRightPoint; if (currentLineRecognizedChars.Any()) { var lineChars = currentLineRecognizedChars.ToDictionary( symbol => symbol, symbol => symbol.StartPoint.Y + symbol.Height); var lowestBound = lineChars.Values.Max(); var lowestSymbol = lineChars.First(symbol => symbol.Value == lowestBound); // Минимальная нижняя точка для текущей линии для распознанных символов var minLineY = currentFragment.StartPoint.Y + lowestSymbol.Key.Height; bottomRightPoint = new Point( currentFragment.StartPoint.X + currentFragment.Width, minLineY); } else { // Нижняя правая точка будет ширина фрагмента. bottomRightPoint = new Point( currentFragment.StartPoint.X + currentFragment.Width, currentFragment.StartPoint.Y + currentFragment.Height + _minimalHeight); } // Мерджим фрагменты которые лежат в прямоугольнике fragment.StartPoint > ! > bottomRightPoint QSymbol[] mergedFragments = unknownFragments.Where( fragment => IsFragmentInsideSquare(fragment, currentFragment.StartPoint, bottomRightPoint)) .ToArray(); EulerMonomap2D currentEuler = EulerMonomap2D.Empty; currentEuler = mergedFragments.Select(fragment => fragment.Euler) .Aggregate(currentEuler, (current, mergedEuler) => current + mergedEuler); QAnalyzedSymbol analyzedSymbol; if (TryFindSymbol(currentFragment, out analyzedSymbol)) { recognizedSymbols.TryAdd(analyzedSymbol); // TODO Symbol стоит смержить, но после всех манипуляций!! Саму картинку currentFragment = currentFragment; return(analyzedSymbol); } // Результат анализа всех букв !!! var resultData = new List <QChar>(); // Идём по всем буквам языка foreach (var possibleSymbol in _knownSymbols) { QChar @char; if (TryIntelliRecognition( possibleSymbol, currentEuler, bottomRightPoint.Y - currentFragment.StartPoint.Y, out @char) && @char.Popularity > _comparer.MinPopularity) { // Не стоит пропускать проверку всех символов, так как стоит найти 3 и з цифро-буквы, либо аналоги А ру. и а англ. resultData.Add(@char); } } return(new QAnalyzedSymbol(currentFragment, resultData)); }