Геометрическая разница областей с внутренними границами с геометрией усиления - PullRequest
1 голос
/ 05 марта 2019

Я бы хотел взять геометрическую разницу двух геометрических объектов с помощью Boost Geometry .Первая геометрия:

enter image description here

У меня всегда есть отрезки, составляющие геометрию.У меня есть координаты и сегменты:

{{-1., -1.}, {1., -1.}, {1., 1.}, {-1., 1.}, {0.6, -1}, {0.6,1.}};
{Line[{{1, 5}, {5, 2}, {2, 3}, {3, 6}, {6, 4}, {4, 1}}], Line[{{5, 6}}]};

где каждый индекс в строках относится к координатам.Любая из геометрий может иметь внутренние границы (и отверстия).

Вторая геометрия:

enter image description here

И я ожидаю получить это:

enter image description here

Я начал с polygon , но я не понимаю, как я мог бы включить внутреннюю границу первого геометрического объекта.В то время как у одного могут быть внутренние отверстия, мне не хватает, как иметь «вырожденный» многоугольник, подобный линии.Также мне не ясно, какой из двух многоугольников будет внешним многоугольником.Тогда я подумал о строке , но там я не могу добавить внутренний сегмент.Можно ли использовать Boost Geometry для нахождения геометрических логических операций для геометрий с внутренними границами, и так, как мне это сделать?

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

#include <iostream>                                                             
#include <fstream>                                                              
#include <list>                                                                 

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

#include <boost/foreach.hpp>                                                    

int main()                                                                      
{                                                                               
    typedef boost::geometry::model::d2::point_xy<double> point_type;            
    typedef boost::geometry::model::polygon<point_type > polygon;               
    //typedef boost::geometry::model::linestring<point_type > line;             

    polygon p1, p2;                                                             
    //line l1, l2;                                                              

    boost::geometry::read_wkt(                                                  
        "POLYGON((-1 -1, 0.6 -1, 1 -1, 1 1, 0.6 1, -1 1))", p1);                

    boost::geometry::read_wkt(                                                  
        "POLYGON((-0.5 -0.5, 2 -0.5, 2 0.5, -0.5 0.5))", p2);                   

    /*                                                                          
    boost::geometry::read_wkt(                                                  
        "LINESTRING(-1 -1, 0.6 -1, 1 -1, 1 1, 0.6 1, -1 1)", l1);               

    boost::geometry::read_wkt(                                                  
        "LINESTRING(-0.5 -0.5, 2 -0.5, 2 0.5, -0.5 0.5)", l2);                  
    */                                                                          

    std::list<polygon> output;                                                  
    boost::geometry::difference(p2, p1, output);                                

    //std::list<line> loutput;                                                  
    //boost::geometry::difference(l2, l1, loutput);                             

    std::ofstream svg("my_map.svg");                                            
    boost::geometry::svg_mapper<point_type> mapper(svg, 400, 400);              

    int i = 0;                                                                  
    BOOST_FOREACH(polygon const& p, output)                                     
    {                                                                           
        mapper.add(p);                                                          
        mapper.map(p, "fill-opacity:0.3;fill:rgb(51,151,53);stroke:rgb(51,151,53);stroke-width:2");  
    }                                                                           

    /*                                                                          
    int i = 0;                                                                  
    BOOST_FOREACH(line const& l, loutput)                                       
    {                                                                           
        mapper.add(l);                                                          
        mapper.map(l, "opacity:0.4;fill:none;stroke:rgb(212,0,0);stroke-width:5");
    }                                                                           
    */                                                                          

    return 0;                                                                   
}

1 Ответ

1 голос
/ 05 марта 2019

Внутренняя линия может быть смоделирована как шип, например, от дно. Это приближение работает:

boost::geometry::read_wkt(
    "POLYGON((-1 -1, 0.6 -1, 0.6 1, 0.60000000000001 -1, 1 -1, 1 1, -1 1))", p1);

Создаются два полигона: маленький нижний правый почти прямоугольник (0.60000000000001 -1, 1 -1, 1 -0.5, 0.6 -0.5) не связан с остальными.

Точный список пунктов

boost::geometry::read_wkt(
    "POLYGON((-1 -1, 0.6 -1, 0.6 1, 0.6 -1, 1 -1, 1 1, -1 1))", p1);

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

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

boost::geometry::read_wkt(
    "POLYGON((-1 -1, 0.6 -1, 0.6 1, -1 1))", p11);
boost::geometry::read_wkt(
    "POLYGON((0.6 -1, 1 -1, 1 1, 0.6 1))", p12);

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

...