Наложение ограничений на 4-точечное преобразование изображения - PullRequest
2 голосов
/ 30 декабря 2010

Я работаю над 4-точечным преобразованием изображения для приложения. Пользователь будет либо перетаскивать каждый угол вокруг, чтобы создать правильную четырехугольную форму, либо использовать его «ограничивающий прямоугольник», чтобы изменить его размеры по вертикали, горизонтали и пропорционально.

Пока у меня работает часть преобразования изображений. Тем не менее, мне трудно наложить ограничения на него, чтобы ...

  1. Вершины не пересекаются друг с другом. Другими словами, я не позволяю пользователю создавать форму песочных часов. Он всегда должен быть четырехугольным.
  2. Аналогично, угол между каждым углом должен быть больше 0. В противном случае вершины окажутся в линии.
  3. Размер этого изображения минимален. То есть каждый угол должен находиться на определенном расстоянии друг от друга и их противоположных линий.
  4. Пользователь не может «перевернуть» изображение на его обратную сторону. 4 угла (p1, p2, p3 и p4) должны появляться по часовой стрелке.
  5. Допустимы вогнутые формы воздушных змеев и треугольники.

Мне было интересно, была ли формула или статья по этим вопросам. В настоящее время у меня есть формулы для определения того, пересекаются ли 2 отрезка (и где), а также для нахождения ближайшей точки на линии к другой точке. Большинство моих реализаций не были удобными для пользователя, как мне нравилось, поскольку углы прыгали повсюду при наложении ограничений.

P.S. Я использую C # для этого проекта, с DirectX. Однако приложение является исключительно 2D.

Ответы [ 2 ]

2 голосов
/ 30 декабря 2010

Мое предложение не налагать ограничения, а просто рисовать, скажем, просто красный каркасный многоугольник, если для вас это неприемлемо.

Это более или менее похоже на то, когда программисты накладывают ограничения на поля ввода формы, например дата начала должна предшествовать дате окончания и не позволять вам вводить дату в поле начала, которое следует за датой в поле конца ... вынуждая пользователей сначала перейти на конечное поле, затем ввести дату окончания, а затем вставить табуляцию вернуться в поле начала, чтобы ввести правильную дату начала.

Просто показывать поля красным НАМНОГО более удобно ... и на самом деле требуется меньше кода.

Захват движений мыши редко является разумной идеей. Если вы не можете применить то, что просит пользователь, просто сделайте это очевидным, а не ограничивая движение ... возможно, пользователь перемещает первую вершину и хочет позже переместить другую вершину в положение, которое сделает ваше преобразование действительным (точно так же, как пример двух полей даты).

Если вы действительно думаете, что ДОЛЖНЫ всегда препятствовать неправильным позициям (и это, например, запретит пользователю переворачивать изображение, даже если ваше преобразование разрешит операцию переворачивания без проблем), то самое простое решение, которое приходит мне в голову, это просто иметь функцию isValid() и просто не перемещать ключевую точку на новую позицию, если она недействительна.

Наличие кода, который «скользит» по недопустимым областям пространства состояний, - довольно сложная обработка IMO, в том числе из-за того, что недопустимые области будут довольно близки к «почти недействительным» областям. Даже в том случае, если «скольжение» является требованием, я бы, вероятно, пошел на реализацию неявного подхода isValid(), выполнив локальный поиск вокруг позиции ключевой точки, чтобы найти ближайшую действительную точку к точке, которую запрашивает пользователь.

Явное вычисление всех возможностей скольжения было бы кошмаром для получения правильной информации и поддержки, если вам нужно что-то изменить в алгоритме преобразования (и, следовательно, в том, что является действительным, а что нет).

0 голосов
/ 30 декабря 2010

Когда вы начинаете, и каждый раз, когда пользователь перемещает маркер, определите набор горизонтальных и вертикальных линий, которые другие маркеры не могут пройти, и установите эти границы во время перетаскивания. Это решит вашу первую проблему.

Для второго, когда мышь перемещается во время перетаскивания, вычислите расстояние между курсором и каждым из трех других маркеров; если оно меньше установленного вами минимального расстояния, переместите ручку по кругу вокруг другой ручки.

...