LINUX.ORG.RU

Какой структурой представить полигон?


0

2

Доброго времени суток, интересует такой вопрос, как можно представить структуру полигона? Есть «классический» вариант с массивом точек, но с такой структурой будут получаться разве что ломано-резанные полигоны. А как быть, если требуются скажем «круглешки-завитушки», скажем полигон в форме клеверного листа?

Т.е вот классический вид:

class Polygon {
public:
    Polygon();

    void AddVertex();
    void DeleteVertex()
    . . .
private:
    vector<Point> mVertex;
};

Все точки хранятся в векторе mVertex. тут все просто, в том числе и определение попадания точки в полигон.

Сейчас думаю сделать следующим образом, хранить в массиве не точки а сегменты. Сегмент, это отдельный класс, который представляет из себя, либо прямую, либо кривую(Безье). Как считаете, это нормальная структура для хранения, есть ли подводные камни? Т.е получается что-то типа такого:

class Segment {
public:
    Segment();
    . . .
private:
    Point P1;
    Point P2;
    Point P3;
    Point P4;
    // точки задают сегмент, используются P1 и P2  если сегмент-линия, и все 4 точки 
    // если это кривая(кубическая кривая Безье), соответсвенно полигон соединяется из 
    // таких вот сегментов, точки привязки Р1 и Р2 если это линия и Р1 и Р4 если это кривая
};

class Polygon {
public:
    Polygon();

    void AddSegment();
    void DeleteSegment()
    bool Intersect(Point p); // определение попадания точки в полигон, одна из нужнейших функций, как её реализовать?
    . . .
private:
    vector<Segment> mSegments;
    vector<Polygon> mHoles;  // "дыры" в полигоне
};

С такой структуром, более-менее можно построить практически любой полигон, но тут остаётся главный для меня вопрос, как определять попадание точки в такой полигон? Кто что скажет? Я так думаю, такой вопрос нужно задавать тем кто программирует всякие GIS, они в этой тебе должны хорошо разбираться.

★★★★★

Последнее исправление: xterro (всего исправлений: 1)

Я не спец по геометрии, но вроде как без последовательности точек, т.е. с отдельными независимыми сегментами, исчезнет такая вещь как winding rule. Что-то мне подсказывает, что хит-функция при этом усложняется донельзя.

arturpub ★★
()

как определять попадание точки в такой полигон

в матлабе функция есть

anonymous
()

Кстати глянул, по bezier curve hittest много чего гуглится. Также хиттесты путей есть во всех векторных либах, можешь просто скачать сорцы какого-нить каиро и подсмотреть, код у них вполне читаемый.

arturpub ★★
()
Ответ на: комментарий от xterro

Значит самопересечений не будет, и есть минимальная толщина линии. Тогда хиттестить можно обычным флудфилом.

arturpub ★★
()
Ответ на: комментарий от arturpub

Интересно, а кривой Безье, можно нарисовать скажем Arc или полукруг? HitTest думал делать с использованием уравнения кривой, т.е подставить туда точку. если равно, то ткнули на линию.

xterro ★★★★★
() автор топика

Полигон дословно переводится как "многоугольник", то есть плоская замкнутая ломаная. Какие ещё у него могут быть "круглешки-завитушки", какие кривые Безье? Вопросы терминологии содержат в себе 90% решения.

dmfd
()
Ответ на: комментарий от arturpub

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

xterro ★★★★★
() автор топика
Последнее исправление: xterro (всего исправлений: 1)
Ответ на: комментарий от xterro

если равно, то ткнули на линию

Аааа... Я сначала подумал, тебе в сам полигон надо попадать. Тогда вообще пофигу как что лежит, хиттест-то тривиальный.

arturpub ★★
()
Ответ на: комментарий от arturpub

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

xterro ★★★★★
() автор топика

полигон в форме клеверного листа

Посмеялся.

Полигоны круглыми не бывают в евклидовых пространствах, выдыхай.

Для хиттеста либо строй битмап, либо делай нормальный полигон и проверяй обычным дедовским способом. Выше головы не прыгнешь.

Почему вариант с сегментами говно - уже пояснили.

schizoid ★★★
()

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

TOXA ★★
()
Ответ на: комментарий от TOXA

Может сделаю и так, пока ещё не определился )

xterro ★★★★★
() автор топика

А как быть, если требуются скажем «круглешки-завитушки»

составлять их из нескольких полигонов.

Bad_ptr ★★★★★
()
Ответ на: комментарий от xterro

Рисуешь свой «полигон», заливаешь цветом, строишь битовую карту: (x, y) залит => принадлежит полигону. Для сложных нетривиальных «полигонов» другого пути нет.

schizoid ★★★
()
Ответ на: комментарий от schizoid

Рисуешь свой «полигон», заливаешь цветом, строишь битовую карту: (x, y) залит => принадлежит полигону. Для сложных нетривиальных «полигонов» другого пути нет.

И с каким же это масштабом нужно рисовать, если нужна хорошая точность по определению принадлежности точки полигону?

Пусть размер полигона около 1000, точность нужна хотя бы 0.001 при определении принадлежности. Как надо рисовать полигон?

kamre ★★★
()
Ответ на: комментарий от kamre

Пусть размер полигона около 1000, точность нужна хотя бы 0.001 при определении принадлежности. Как надо рисовать полигон?

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

schizoid ★★★
()
Ответ на: комментарий от schizoid

То, что рисовать нужно будет отрезками - это очевидно. Но какой будет размер картинки в пикселях для такой точности? Предлагается на 1000000x1000000 рисовать при предложенном подходе?

kamre ★★★
()
Ответ на: комментарий от kamre

Хитпоинт обычно в единицах грануляции прилетает, от них и танцуем.

arturpub ★★
()
Ответ на: комментарий от kamre

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

arturpub ★★
()
Ответ на: комментарий от kamre

Если отрезками рисовать - битмап не нужен. Почему ты такой тупой?

schizoid ★★★
()
Ответ на: комментарий от Harald

В идеале с любыми. По задумке, как задам полигон, так он и должен отрисоваться. Т.е скажем, есть конфиг(условно):

Polygon {
    Line 1000 1000 5000 5000 1 1
    Line 2000 1000 6000 2000 1 1
    Line 3000 1000 7000 8000 1 1
    Arc 3000 1000 90 180 1 1 2
    Arc 4000 3000 180 270 1 1 3
    Polygon {
      ...
    }
    Options solid 3  
}

Программа читает это дело и рисует. Пока можно абстрагироваться от плат и моей «вундервафли» как таковой. Есть задача, нарисовать полигон, посему изучаю оптимальные для себя способы его задания и вычисления некоторых функций над ним(попадание точки, пересечение с другим полигоном, пересечение с линией) :)

xterro ★★★★★
() автор топика

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

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

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

no-dashi ★★★★★
()
Последнее исправление: no-dashi (всего исправлений: 2)

Мне тут вот подумалось, если полигон состоит из сегментов(типа line и arc) то имеет ли смысл вообще заводить ткую структуру как полигон? Достаточно завести структуру Polyline, соответсnвенно .если первая и последняя точка этой polyline равны, то это полигон :)

xterro ★★★★★
() автор топика

Если код открытый, то можно взять файлы G4ClippablePolygon.hh(.icc .cc) из проекта CERN Geant4.
Класс навороченный и на все грабли там уже наступили, см. paste.

blinkenlichten
()
Ответ на: комментарий от no-dashi

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

не, на треугольники как раз разбивают, чтобы получить время O(log n) при предобработке O(n)

Waterlaz ★★★★★
()
Ответ на: комментарий от no-dashi

А разве обход сегментов(когда точка для каждого сегмента должна быть с одной стороны) для определения попадания точки в полигон не проще, чем разбиение на треугольники?

xterro ★★★★★
() автор топика
Последнее исправление: xterro (всего исправлений: 1)
Ответ на: комментарий от xterro

Если у тебя контур всегда представляет выпуклый многоугольник - то - да, проще. Если нет (контур имеет произвольную форму) - всё, попадалово.

no-dashi ★★★★★
()
Ответ на: комментарий от anonymous

Давайте конструктивно, без оскорблений )

xterro ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.