示例#1
0
        private List <LineCluster> ClusterLines(CachedJunctionCombinations cachedJunctionCombinations, List <Line> possibleSol)
        {
            Dictionary <int, Junction[]> junctionsPerGroup = VerticalGroupJunctions(cachedJunctionCombinations, possibleSol);

            List <LineCluster> lineClusters = HorizontalGroupLines(junctionsPerGroup);

            return(lineClusters);
        }
示例#2
0
        private Dictionary <int, Junction[]> VerticalGroupJunctions(CachedJunctionCombinations cachedJunctionCombinations, List <Line> possibleSol)
        {
            // Let's merge near junctions. (vertical line)
            // We assign a group id for each clusters.

            Dictionary <int, int> junctionToGroupId = new Dictionary <int, int>();

            int nextGroupId = 1;

            foreach (var curSolution in possibleSol)
            {
                if (curSolution.Junctions.First().GroupId == 0)
                {
                    for (int i = 0; i < curSolution.Junctions.Length; i++)
                    {
                        ref var j = ref curSolution.Junctions[i];
                        j.GapX = curSolution.GapX;
                    }

                    // Not assigned yet.

                    // Find near junction.
                    int groupId = 0;

                    foreach (var item in curSolution.Junctions)
                    {
                        var alreadyClassified = cachedJunctionCombinations.cacheNearJunction[BuildDictionaryId(item.X, item.Y)]
                                                .Where(m =>
                                                       // Doesn't work with struct.
                                                       //m.GroupId != 0 &&
                                                       //TODO: More hardcoding
                                                       Math.Abs(m.X - item.X) <= 5 &&
                                                       Math.Abs(m.Y - item.Y) <= 3
                                                       // Doesn't work with struct.
                                                       //Math.Abs(m.GapX - item.GapX) <= 2
                                                       ).Where(m => junctionToGroupId.ContainsKey(BuildDictionaryId(m.X, m.Y)));
                        if (alreadyClassified.Any())
                        {
                            Junction junction = alreadyClassified.First();
                            groupId = junctionToGroupId[BuildDictionaryId(junction.X, junction.Y)];
                            //groupId = alreadyClassified.First().GroupId;
                            break;
                        }
                    }

                    if (groupId == 0)
                    {
                        // Not found.
                        // Create a new group.
                        nextGroupId++;

                        groupId = nextGroupId;
                    }

                    for (int i = 0; i < curSolution.Junctions.Length; i++)
                    {
                        ref var j = ref curSolution.Junctions[i];
                        j.GroupId = groupId;
                        int id = BuildDictionaryId(j.X, j.Y);
                        if (!junctionToGroupId.ContainsKey(id))
                        {
                            junctionToGroupId.Add(id, groupId);
                        }
                    }
                }
示例#3
0
        private List <Line> GetLines(List <Junction> listJunction, CachedJunctionCombinations junctionCombinations)
        {
            // Let's check the list of points.

            int numSol = 0;

            List <Line> possibleSol = new List <Line>();

            // We use a dictionary here because we need a fast way to remove entry.
            // We reduce computation and we also merge solutions.
            var elements = listJunction.OrderBy(m => m.Y).ToDictionary(m => BuildDictionaryId(m.X, m.Y), m => m);

            int skipSol = 0;

            while (elements.Any())
            {
                var start = elements.First().Value;
                elements.Remove(BuildDictionaryId(start.X, start.Y));

                Dictionary <int, List <int> > usedJunctionsForGapX = new Dictionary <int, List <int> >();
                List <Line> listSolutions   = new List <Line>();
                var         junctionsForGap = junctionCombinations.cacheNearJunction[BuildDictionaryId(start.X, start.Y)];

                for (int iGap = 0; iGap < junctionsForGap.Length; iGap++)
                {
                    var gap = junctionsForGap[iGap];

                    // Useless because it's already done with: cacheNearJunction.

                    /*
                     *                  var gapY = Math.Abs(gap.Y - start.Y);
                     *                  if (gapY > 2)
                     *                  {
                     *                          continue;
                     *                  }*/

                    var gapX = Math.Abs(gap.X - start.X);
                    if (gapX <= this.Options.minX || gapX > this.Options.maxX)
                    {
                        continue;
                    }

                    // We will reduce list of solution by checking if the solution is already found.
                    //if (listSolutions.Any(m => Math.Abs(m.GapX - gapX) < 2 && m.Junctions.Contains(start)))
                    if (usedJunctionsForGapX.ContainsKey(BuildDictionaryId(gap.X, gap.Y)) &&
                        usedJunctionsForGapX[BuildDictionaryId(gap.X, gap.Y)].Any(m => Math.Abs(m - gapX) < 10))
                    {
                        skipSol++;
                        continue;
                    }

                    List <Junction> curSolution = new List <Junction>();
                    curSolution.Add(start);

                    int numElementsRight = FindElementsOnDirection(junctionCombinations.cachePossibleNextJunctionRight, start, gapX, curSolution);
                    int numElementsLeft  = FindElementsOnDirection(junctionCombinations.cachePossibleNextJunctionLeft, start, -gapX, curSolution);

                    int numElements = numElementsLeft + numElementsRight;

                    if (numElements >= this.Options.MinNumElements)
                    {
                        if (numSol == this.Options.MaxSolutions)
                        {
                            // Something wrong happen. Too much solution for now.
                            // If we continue, we would spend too much time processing the image.
                            // Let's suppose we don't know.
                            throw (new Exception("Too much solution somehow"));

                            /*
                             * return new OpenFieldReaderResult
                             * {
                             *  // Too much solution. You may want to increase MaxSolutions.
                             *  ReturnCode = 30
                             * };
                             */
                        }

                        numSol++;
                        listSolutions.Add(new Line
                        {
                            GapX      = gapX,
                            Junctions = curSolution.ToArray()
                        });
                        foreach (var item in curSolution)
                        {
                            List <int> listGapX;
                            if (!usedJunctionsForGapX.ContainsKey(BuildDictionaryId(item.X, item.Y)))
                            {
                                listGapX = new List <int>();
                                usedJunctionsForGapX.Add(BuildDictionaryId(item.X, item.Y), listGapX);
                            }
                            else
                            {
                                listGapX = usedJunctionsForGapX[BuildDictionaryId(item.X, item.Y)];
                            }
                            listGapX.Add(gapX);
                        }
                    }
                }

                Line bestSol = listSolutions.OrderByDescending(m => m.Junctions.Count()).FirstOrDefault();

                if (bestSol != null)
                {
                    // Too slow. (faster if we skip removal)
                    // But, we have more solutions.
                    foreach (var item in bestSol.Junctions)
                    {
                        elements.Remove(BuildDictionaryId(item.X, item.Y));
                    }

                    possibleSol.Add(bestSol);
                }
            }

            if (this.Options.Verbose)
            {
                this.Logger.LogSolutions(numSol, possibleSol, skipSol);
            }

            return(possibleSol);
        }