CGAL 2D сегментный адаптер Вороного с информацией - PullRequest
0 голосов
/ 05 марта 2020

Я бы хотел прикрепить информацию к сайтам 2D сегмента диаграммы Вороного. Поскольку я не нашел способа сделать это с помощью адаптера диаграммы Вороного напрямую, я сначала строю двухмерный сегмент триангуляции Делоне, а затем создаю адаптер диаграммы Вороного с триангуляцией Делоне в качестве аргумента конструктора.

При построении Делоне триангуляции прикрепляю информацию к сайтам. Для этого я использовал (по-видимому, не задокументировано) Segment_Delaunay_graph_storage_traits_with_info_2, как описано в этом примере: https://doc.cgal.org/latest/Segment_Delaunay_graph_2/Segment_Delaunay_graph_2_2sdg-info-set_8cpp-example.html

Теперь проблема в том, что я не могу получить информацию о сайте во время итерации по краям диаграммы Вороного: eit->up()->storage_site().info_has_been_set() и eit->down()->storage_site().info_has_been_set() (где eit - итератор ребер) оба имеют значение false. Информация о сайте доступна через оригинальную триангуляцию Делоне.

Итак, мой вопрос, как получить доступ к информации о сайте через адаптер Вороного? И если да, то как мне построить диаграмму Вороного с максимально эффективной информацией?

У меня есть следующий код для определений типов:

#include <CGAL/Simple_cartesian.h>
typedef CGAL::Simple_cartesian<double> K;
// typedefs for the traits and the algorithm
#include <CGAL/Segment_Delaunay_graph_2.h>
#include <CGAL/Segment_Delaunay_graph_filtered_traits_2.h>
#include <CGAL/Segment_Delaunay_graph_storage_traits_with_info_2.h>

#include "TrianSiteInfoSet.h"

typedef CGAL::Segment_Delaunay_graph_filtered_traits_without_intersections_2<K> Gt;

// define the info and the convert and merge functors
struct Info_item {
    int polyline_id;

    Info_item (int polyline_id)
        : polyline_id(polyline_id)
    {
    }
};
typedef Info_set<Info_item>                 Info;
typedef Info_set_convert_info<Info_item>    Convert_info;
typedef Info_set_merge_info<Info_item>      Merge_info;

// define the storage traits with info
typedef
CGAL::Segment_Delaunay_graph_storage_traits_with_info_2<Gt,
                                                        Info,
                                                        Convert_info,
                                                        Merge_info>
ST;

typedef CGAL::Segment_Delaunay_graph_2<Gt, ST>  SDG2;


#include <CGAL/Voronoi_diagram_2.h>
#include <CGAL/Segment_Delaunay_graph_adaptation_traits_2.h>
#include <CGAL/Segment_Delaunay_graph_adaptation_policies_2.h>
typedef CGAL::Segment_Delaunay_graph_adaptation_traits_2<SDG2>               AT;
typedef CGAL::Segment_Delaunay_graph_degeneracy_removal_policy_2<SDG2>       AP;
typedef CGAL::Voronoi_diagram_2<SDG2,AT,AP>                                  VD;

#include <CGAL/Segment_Delaunay_graph_site_2.h>

Типы Info_set, Info_set_convert и Info_set_merge_info такие же, как в https://doc.cgal.org/latest/Segment_Delaunay_graph_2/Segment_Delaunay_graph_2_2sdg-info-set_8cpp-example.html

Вот код, соответствующий тому, что я объяснил выше:

SDG2 sdg;
// Construct the Delaunay Triangulation
for (unsigned int i = 0; i < polylines.size(); i++)
{
    std::vector<Gt::Segment_2> segments;
    ConvertPolylineToSegmentVector (polylines[i], segments);
    for (unsigned int s = 0; s < segments.size(); s++)
    {
        SDG2::Site_2 site;
        site = site.construct_site_2(segments[s].source(), segments[s].target());
        sdg.insert (site, Info(Info_item(i)));
    }
}

VD vd(sdg);
// Draw the Voronoi diagram vd
QPen pen;
for (VD::Edge_iterator eit = vd.edges_begin(); eit != vd.edges_end(); eit++)
{
    if (eit->is_segment())
    {
        VD::Vertex_handle source = eit->source(),
                          target = eit->target();

        // NOTE/TODO: we only compare the first elements, we should actually compare the complete list for common id's
        if (eit->up()->storage_site().info_has_been_set() && eit->down()->storage_site().info_has_been_set() &&
            eit->up()->storage_site().info().info_items_begin()->polyline_id
               != eit->down()->storage_site().info().info_items_begin()->polyline_id)
        {
            if ((eit->up()->site().is_segment() && eit->down()->site().is_segment()) ||
                (eit->up()->site().is_point() && eit->down()->site().is_point()))
            {
                pen.setColor(QColorConstants::Red);
            }
            else
            {
                // use green lines to indicate that the straight line visualisation is wrong since it should actually be a parabolic arc
                pen.setColor(QColorConstants::Green); 
            }
        }
        else
        {
            pen.setColor(QColorConstants::LightGray);
        }
        QGraphicsItem *new_item = ui->widget->GetScene()->addLine(source->point().x(), source->point().y(),
                                                                  target->point().x(), target->point().y(),
                                                                  pen);
        output_graphics_items.push_back (new_item);
    }
}
...