qqwe Любой пиксель, цвет которого отличается от P(0, 0) не принадлежит фону. Это задача не на распознавание предметов или есчо чего либо.
Посмотрел я на ваш рисунок и ко мне пришла идея. Можно растр хранить не просто в виде растра обычного, а в виде разряженной матрицы, которая описывает только контур фигуры (ведь нам нужен только контур?). Тогда при правильной структуре такой матрицы можно действительно повысить скорость обработки. Мне видится примерно такая структура: Код (Text): Строка1: 0 Строка2: {x1,y1},{x2,y2} Строка3: {x1,y1},{x2,y2},{x3,y3},{x4,y4} Строка4: {x1,y1},{x2,y2},{x3,y3},{x4,y4} Строка5: {x1,y1},{x2,y2} Строка6: 0 При этом, не сложно доказать для замкнутых фигур, что в одной строке всегда четное количество точек. Проверка пересечения сводится к выяснению, случаем все ли четные точки лежат между нечетной и четной другой фигуры и, соответственно, все ли нечетные точки лежат между четной (считая нулевую) и нечетной. Вроде, достаточно резво смотрится. Точность остается до пикселя, как и требуется, но будет тратится один проход по фигуре для самопальной "трассировки" до разряженной матрицы.
hivemind Структура немного иной должна быть, это массив пиксель поверхности, где каждый пиксель описан двумя координатами и вектором. Тогда после описания обеих поверхностей трассируем тестируемую поверхность и для каждой точки этой поверхности проверяем условие вхождения в фигуру(трассируем её поверхность и проверяем условие выше). При выделении поверхности не будут затрагиваться внутренние точки фигуры, а только фон, тоесть по сути фон становится фигурой(а фигуры так скажем "дырками"). Если фигура содержит вложенные фигуры, тоесть отдельные учатки фона, то следует их обьеденить линиями с исходной поверхностью(это реализуется алго заливки используя эти свойства поверхности).
gaeprust Вообще-то четное количество точек у меня заменяет информацию о векторах. Только у нас один аспект упущен из виду - а что если мы имеем горизонтальную прямую? Куда укажут ваши вектора тогда? Ну а у меня нарушится четность с вероятностью 0.5 Надо тогда вводить наверно не два вектора, а флаг: - слева пусто-справа фигура - справа пусто-слева фигура - слева фигура-справа фигура Слева пусто-справа пусто - такой флаг нам не нужен, ибо в разряженной матрице таких точек мы держать не будем
hivemind Все точки горизонтальной прямой будут принадлежать поверхности. Вектор и определяет положение фигуры, в данном случае(на скрине выше) фигура находится справа от точки поверхности, в которой вектор направлен вниз. Вот две фигуры пересекаются. Изображена только поверхность. Точки между двумя точками поверхности, в которых V = Down и V' = Up, где X' > X принадлежат фигуре, как сказано выше. Значит делаем вывод, что фигуры пересекаются, если точка поверхности первой фигуры лежит между точками другой поверхности с условием выше. Также все точки лежащие на одной прямой между двумя точками обеих поверхностей являются общими для обеих фигур.
gaeprust В принципе логично. Только вот я не понимаю, вы уже написали сюда алгоритм. Создается просто впечатление, что написать программу должен я... Кстати, вы отлично заметили, что если работать со строками в массиве, то хранить Y у точек не обязательно На самом деле "мой" флаг и "ваши" вектора - суть одно и то же. Только почему-то мне кажется, что будет удобнее все же работать как с флагом, хоть вектора и единичные. Конечно, если векторы не "вырождать" в флаг. Но это не принципиально.
hivemind Вот написал небольшой псевдокод(это блок-схема, только текстовая). Условно присвоим значения вектору V от нуля циклически по часовой стрелке, тоесть 0: Up, 1: Right.., тогда поверхность будет описывать следующий код(если V = Down, то поверхность справа, так удобнее): Код (Text): if V = Up if Point(X + 1, Y + 1) X = X + 1 Y = Y + 1 V = Right elseif Point(X, Y + 1) Y = Y + 1 else V = Left fi elseif V = Right if Point(X + 1, Y - 1) X = X + 1 Y = Y - 1 V = Down elseif Point(X + 1, Y) X = X + 1 else V = Up fi elseif V = Down if Point(X - 1, Y - 1) X = X - 1 Y = Y - 1 V = Left elseif Point(X, Y - 1) Y = Y - 1 else V = Right fi elseif V = Left if Point(X - 1, Y + 1) X = X - 1 Y = Y + 1 V = Up elseif Point(X - 1, Y) X = X - 1 else V = Down fi fi Лучше описать дельту координат в двух массивах T1 и T2, тогда: Код (Text): Step(*X, *Y, *V): X0 = X Y0 = Y Do if Point(X + T1.dX{V}, Y + T1.dY{V}) X = X + T1.dX{V} Y = Y + T1.dY{V} V = V + 1 elseif Point(X + T2.dX{V}, Y + T2.dY{V}) X = X + T2.dX{V} Y = Y + T2.dY{V} else V = V - 1 fi Loop (X <> X0) or (Y <> Y0) ret T1{ dX dY +1 +1 +1 -1 -1 -1 -1 +1 } T2{ dX dY 0 +1 +1 0 0 -1 -1 0 } На основе этого кода можем описать поверхность: Код (Text): CreateSurface(X, Y, P{}): V = 2 ; Down, поверхность справа. X0 = X Y0 = Y !dV ; Флаг изменения вектора V. !J ; Индекс описателя точки в массиве P{}. Do P{J} = (X, Y, V) Step(X, Y, V) if V <> 2 dV = TRUE fi J = J + 1 Loop (X = X0) & (Y = Y0) & (V = 2) & dV ret Тогда код, определяющий принадлежность точки фигуре будет следующим: Код (Text): P - координаты проверяемой точки. S - координаты границы фигуры(она справа от этой точки). ; IsPointBelongToFigure(Px, Py, Sx, Sy): CreateSurface(Sx, Sy, P{}) if P{Px, Py} ; Точка принадлежит поверхности. End TRUE fi A{X, Y} = FindLeftPoint(P{}, Px, Py) ; Ищем точку слева. if A{} ; Если точка найдена. B{X, Y} = FindRightPoint(P{}, Px, Py) ; Ищем точку справа. if B{} ; Точка справа найдена. As{X, Y, V} = FindPointInSurface(P{}, A{}) ; Ищем левую точку на поверхности. Bs{X, Y, V} = FindPointInSurface(P{}, B{}) ; И правую. if As & Bs ; С двух сторон есть поверхность. if As.X{} < Bs.X{} As.X{} xchg Bs.{X} fi if (As.V{} = 2) & Bs.V{} ; Проверяем вектора(Up...P...Down). End TRUE fi fi fi fi Определение пересечения в таком случае будет сводится к перечислению точек поверхности и для каждой проверку IsPointBelongToFigure() с дополнительной проверкой векторов, но это тривиально и лень описывать. Для ускорения можно связать ссылками описатели в массивах(тоесть точка поверхности слева - и справа). В таком случае получится граф, на формирование которого времени уйдет больше, чем просто линейный проход по массиву.