Boost :: Геометрия пересечения не работает должным образом - PullRequest
2 голосов
/ 28 ноября 2011

У меня есть небольшое тестовое приложение, которое пересекает несколько прямоугольников с помощью boost :: geometry.

typedef boost::geometry::model::point
<
double, 2, boost::geometry::cs::cartesian
> point;

typedef boost::geometry::model::polygon<point > polygon;

polygon Intersect(polygon p1, polygon p2) {
    std::vector < polygon > result;
    boost::geometry::intersection(p1, p2, result);
    return result.front();
}

polygon IntersectionTest() {
    polygon one, two, three, four;

    boost::geometry::read_wkt("POLYGON((35 25, 35 35, 15 35, 15 25, 35 25))", one);
    boost::geometry::read_wkt("POLYGON((45 30, 45 50, 25 50, 25 30, 45 30))", two);
    boost::geometry::read_wkt("POLYGON((50  0, 50 40, 10 40, 10  0, 50  0))", three);
    boost::geometry::read_wkt("POLYGON((40 20, 40 60,  0 60,  0 20, 40 20))", four);

    return Intersect(Intersect(Intersect(one, two), three), four);
}

Я должен сделать что-то не так, потому что я ожидаю, что результат будет примерно таким же, как (35 30, 35 40, 25 40, 25 30, 35 30), но я получаю многоугольники длиной 10 точек, содержащие такие точки, как 50 0, тогда как пересечения параллельных прямоугольников всегда должны быть прямоугольниками с 4 + 1 точками и 50 0 на краю, поэтому он не должен быть на пересечении вообще. Если я положу его в SVG , то прямоугольники будут такими, как я ожидал.

Что может быть не так? Если это ошибка в boost::geometry, как я могу убедиться в этом? (В настоящее время я использую 1.48.) Если это ошибка, есть ли способ обойти проблему?

Ответы [ 2 ]

2 голосов
/ 19 января 2012

Я согласен с ответом ds27680.

Третий вариант - вызвать boost :: geometry :: correct (geometry) после read_wkt, и пользователям рекомендуется делать это, если не уверены в ориентации.

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

2 голосов
/ 28 ноября 2011

Класс полигона имеет следующие параметры шаблона:

template
<
    typename Point,
    bool ClockWise = true,
    bool Closed = true,
    template<typename, typename> class PointList = std::vector,
    template<typename, typename> class RingList = std::vector,
    template<typename> class PointAlloc = std::allocator,
    template<typename> class RingAlloc = std::allocator
>
class polygon {...}

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

На самом деле это ваша проблема.

Если вы посмотрите на свою геометрию WKT, то вы написали точки против часовой стрелки.

Так что вам следует либо:

typedef boost::geometry::model::polygon<point,false> polygon;

Или запишите точки в строке WKT по часовой стрелке.Т.е.:

boost::geometry::read_wkt("POLYGON((35 25, 15 25, 15 35, 35 35, 35 25))", one);
boost::geometry::read_wkt("POLYGON((45 30, 25 30, 25 50, 45 50, 45 30))", two);

При этом результат будет таким, как вы ожидали.

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

...