Поведение boost :: geometry :: inside () для точки и сегмента - PullRequest
0 голосов
/ 02 октября 2018

В настоящее время я использую повышение 1.67 и обнаруживаю, что если я использую boost::geometry::within(), чтобы проверить, находится ли точка в сегменте, я не получу ожидаемых ответов.Например, я могу построить пару отрезков, которые пересекаются, и использовать boost::geometry::intersection(), чтобы получить точку пересечения.Я ожидаю, что эта точка будет в пределах каждого из краев.Однако это не всегда то, что я вижу.Вот код, демонстрирующий мою проблему:

#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>

int main() {
    using point_t = boost::geometry::model::d2::point_xy<double>;
    using segment_t = boost::geometry::model::segment<point_t>;
    segment_t e1{point_t{100, 350}, point_t{-100, 400}};
    segment_t e2{point_t{0, 0}, point_t{90, 600}};
    std::vector<point_t> iv;
    boost::geometry::intersection(e1, e2, iv);
    assert(iv.size() == 1);
    const auto& v = iv[0];
    bool is_within = boost::geometry::within(v, e1);
    std::cout << "is within? " << is_within << std::endl;
    is_within = boost::geometry::within(v, e2);
    std::cout << "is within? " << is_within << std::endl;

    return 0;
}

В этом случае within() возвращает false для обоих ребер.

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Я собираюсь опубликовать это как ответ в надежде, что это может быть полезно для других в будущем.Если вам нужно проверить, что данный point лежит на segment, не используйте within() (или covered_by(), в этом отношении).В комментариях к исходному вопросу @ rafix07 предложил более полезный подход к решению этой проблемы: используйте boost::geometry::distance(point, segment).Вы можете установить соответствующий допуск для вашей ситуации, и если измеренное расстояние попадает в него, объявить победу и двигаться дальше.

0 голосов
/ 02 октября 2018

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

Всего у вас есть две проблемы:

  • boost::geometry::within вернет false для точек, которые находятся точно на границе геометрического объекта, что будет иметь место для всех точек на линии.Вам нужно изменить стратегию, чтобы разрешить within возвращать true для точек, находящихся на границе.
  • Расчет пересечения двух точек обычно приводит к некоторой степени ошибки во время математики с плавающей запятой.Вы не можете гарантировать, что точка, определенная как пересечение двух линий, находится буквально на любой линии.Вам нужно разрешить определенную степень допуска на расстоянии до значения дельты (определенного вами, я бы не стал превышать одну десятитысячную), чтобы разрешить рассматривать как «пересекающуюся» линию.
...