Ваше описание не на сто процентов ясно для меня, но если я вас правильно понимаю, вы хотите вычислить следующее:
- множество смежных точек цвета A, которые находятся рядомв цветную точку B
- , которая содержит заданную начальную точку.
Учитывая эту спецификацию, ваш код практически сам себя пишет.Единственное, с чем вам нужно сейчас определиться, это то, что означает «непрерывное соединение» (например, являются ли пиксели смежными только по их углам или нет?).
Кроме того, ваше описание неоднозначно.Рассмотрим y-образную область, где плечи области имеют ширину в один пиксель: это будет иметь три «конечных точки», если вы определите конечную точку как «член набора с одним соседом также в наборе».Если вы ослабите свое требование разрешить любое количество конечных точек, тогда ваш код может собирать набор конечных точек по ходу.
РЕДАКТИРОВАТЬ
Рад, что вы решили свою проблему.Я набросал решение, которое производит это для вашей типовой задачи:
1111***2222
111**222222
111*2222222
111*2222222
111***22222
11111*33322
11333333333
Вот код, предоставленный только потому, что мне нужна проверка для его кодирования :-) Он написан для ясности, а не для скорости.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace StackOverflowEdgeDetection
{
class Program
{
private static HashSet<Point> FindBorder(char[,] grid, Point start, char inside, char outside)
{
var border = new HashSet<Point> {};
var endpoints = new HashSet<Point> { start };
while (endpoints.Count != 0)
{
var p = endpoints.First();
endpoints.Remove(p);
border.Add(p);
var newEndpoints = Neighbours(p).Where(q =>
Grid(grid, q) == inside &&
!border.Contains(q) &&
Neighbours(q).Any(r => Grid(grid, r) == outside)
);
endpoints.UnionWith(newEndpoints);
}
return border;
}
private static IEnumerable<Point> Neighbours(Point p)
{
yield return new Point(p.X - 0, p.Y - 1);
yield return new Point(p.X + 1, p.Y - 1);
yield return new Point(p.X + 1, p.Y + 0);
yield return new Point(p.X + 1, p.Y + 1);
yield return new Point(p.X + 0, p.Y + 1);
yield return new Point(p.X - 1, p.Y + 1);
yield return new Point(p.X - 1, p.Y - 0);
yield return new Point(p.X - 1, p.Y - 1);
}
public static char Grid(char[,] grid, Point p) {
var x = p.X;
var y = p.Y;
var height = grid.GetLength(0);
var width = grid.GetLength(1);
return (0 <= x && x < width && 0 <= y && y < height) ? grid[y, x] : '\0';
}
static void Main(string[] args)
{
var border = FindBorder(TestGrid, TestStart, TestInside, TestOutside);
var points = Enumerable.Range(0, TestHeight)
.SelectMany(y => Enumerable.Range(0, TestWidth)
.Select(x => new Point(x, y)));
foreach (var p in points) {
Console.Write(border.Contains(p) ? '*' : Grid(TestGrid, p));
if (p.X + 1 == TestWidth) Console.WriteLine();
}
Console.ReadLine();
}
private static readonly char[,] TestGrid = new char[,] {
{ '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2' },
{ '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2' },
{ '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2' },
{ '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2' },
{ '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2' },
{ '1', '1', '1', '1', '1', '1', '3', '3', '3', '2', '2' },
{ '1', '1', '3', '3', '3', '3', '3', '3', '3', '3', '3' }
};
private static readonly Point TestStart = new Point(3, 3);
private static readonly Point TestAdjacent = new Point(4, 3);
private static readonly char TestInside = Grid(TestGrid, TestStart);
private static readonly char TestOutside = Grid(TestGrid, TestAdjacent);
private static readonly int TestWidth = TestGrid.GetLength(1);
private static readonly int TestHeight = TestGrid.GetLength(0);
}
}