Я бы хотел прикрепить информацию к сайтам 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);
}
}