Exemple #1
0
        /// <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));
        }