/// <summary> /// If the given file source is conflicting, it will be added to <see cref="ConflictingFileSources"/>. /// Conflicted file sources are file sources that are pending but locked due to a thread currently /// processing an identical source. /// </summary> /// <param name="source">The source that will be checked if it is conflicting and (maybe) added.</param> /// <returns><code>true</code> if the file source is currently active or already pending (i.e. conflicting); /// <code>false</code> otherwise.</returns> protected virtual bool TryAddConflicting(IFileSource source) { var conflicts = PendingFileSources .Where(s => FileSourceComparer.Equals(s, source)) .Concat( ActiveFileSources.Where(s => FileSourceComparer.Equals(s, source)) ).ToArray(); if (conflicts.Any()) { ConflictingFileSources.Add(source, new HashSet <IFileSource>(conflicts)); return(true); } return(false); }
/// <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)); }