44 for (
auto const &p :
cell) {
47 auto cgal_centroid = CGAL::centroid(polygon.begin(), polygon.end());
51 centroid_ = centroid_ / mass_;
55void Voronoi::CellNavigator(
57 std::function<
void(
double,
Point2)> evaluator_func) {
58 auto const &cell = vcell.
cell;
62 for (
int i = 1; i < n; ++i) {
63 if (cell[i].x() < cell[left_id].x()) {
66 if (cell[i].x() > cell[right_id].x()) {
71 int min_i = std::round(cell[left_id].x() / resolution_);
72 min_i = min_i < 0 ? 0 : min_i;
74 int max_i = std::round(cell[right_id].x() / resolution_);
75 max_i = max_i > map_size_.x() ? map_size_.x() : max_i;
77 auto next_id = [=](
int const id) {
return (
id + 1) % n; };
78 auto prev_id = [=](
int const id) {
return id == 0 ? (n - 1) : (id - 1); };
80 auto cc_pt_id = next_id(left_id);
81 auto c_pt_id = prev_id(left_id);
83 for (
int i = min_i; i < max_i; ++i) {
84 double x = i * resolution_ + resolution_ / 2.;
86 if (cc_pt_id == left_id) {
89 if (cell[cc_pt_id].x() < x) {
90 cc_pt_id = next_id(cc_pt_id);
96 if (c_pt_id == left_id) {
99 if (cell[c_pt_id].x() < x) {
100 c_pt_id = prev_id(c_pt_id);
106 if (cell[cc_pt_id].x() < x) {
109 if (cell[c_pt_id].x() < x) {
113 auto prev_pt = cell[prev_id(cc_pt_id)];
114 auto cc_pt = cell[cc_pt_id];
115 auto x1 = prev_pt.x();
116 auto y1 = prev_pt.y();
120 if ((x2 - x1) <
kEps) {
121 throw std::runtime_error{
"Unexpected error!"};
123 auto y_lower = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
125 auto next_pt = cell[next_id(c_pt_id)];
126 auto c_pt = cell[c_pt_id];
132 if ((x2 - x1) <
kEps) {
133 throw std::runtime_error{
"Unexpected error!"};
135 auto y_upper = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
137 int min_j = std::round(y_lower / resolution_);
138 min_j = min_j < 0 ? 0 : min_j;
140 int max_j = std::round(y_upper / resolution_);
141 max_j = max_j > map_size_.y() ? map_size_.y() : max_j;
143 for (
int j = min_j; j < max_j; ++j) {
144 double y = j * resolution_ + resolution_ / 2.;
145 Point2 curr_pt(x, y);
146 auto map_val = map_->operator()(i, j);
147 evaluator_func(map_val, curr_pt);
152void Voronoi::ComputeMassCentroid(VoronoiCell &vcell) {
154 if (compute_single_ ==
true) {
155 vcell.origin_shift = origin_shift_;
159 std::placeholders::_1, std::placeholders::_2);
160 CellNavigator(vcell, fp);
161 vcell.ComputeFinalCentroid();
168 if (num_sites_ == 1) {
170 vcell.
site = sites_[0];
172 Point2{map_size_.x(), map_size_.y()},
173 Point2{0, map_size_.y()}};
174 ComputeMassCentroid(vcell);
175 if (compute_single_ ==
true) {
176 voronoi_cell_ = vcell;
178 voronoi_cells_[0] = vcell;
185 std::vector<CGAL_Point2> CGAL_sites;
186 CGAL_sites.reserve(num_sites_);
188 for (
auto const &pt : sites_) {
191 dt2.insert(CGAL_sites.begin(), CGAL_sites.end());
211 if (seg.is_degenerate()) {
214 CGAL::insert(arr, seg);
218 CGAL::insert(arr, vor.
rays_.begin(), vor.
rays_.end());
226 CGAL::insert(arr, vor.
lines_.begin(), vor.
lines_.end());
239 std::vector<CGAL_Query_result> query_results_vor, query_results_vor_sorted;
240 if (compute_single_ ==
true) {
241 auto pt = CGAL_sites[robot_id_];
242 std::list<CGAL_Point2> temp_site; temp_site.push_back(pt);
243 CGAL::locate(arr, temp_site.begin(), temp_site.end(), std::back_inserter(query_results_vor));
245 const Arrangement_2::Face_const_handle* f;
246 if ((f = std::get_if<Arrangement_2::Face_const_handle>(&query_results_vor[0].second))) {
247 if((*f)->is_unbounded()) {
248 throw std::runtime_error{
"inside the unbounded face."};
251 throw std::runtime_error{
"Invalid object."};
254 if (not polygon.is_counterclockwise_oriented()) {
255 polygon.reverse_orientation();
258 for (
auto const &p : (polygon)) {
262 voronoi_cell_.
cell = poly_points;
264 ComputeMassCentroid(voronoi_cell_);
274 CGAL::locate(arr, CGAL_sites.begin(), CGAL_sites.end(), std::back_inserter(query_results_vor));
277 for (
int i = 0; i < num_sites_; ++i) {
279 auto it = std::find_if(query_results_vor.begin(), query_results_vor.end(),
281 return qr.first == CGAL_sites[i];
283 if (it == query_results_vor.end()) {
284 throw std::runtime_error{
"Could not find a query result"};
286 query_results_vor_sorted.push_back(*it);
289#pragma omp parallel for num_threads(num_sites_)
290 for (
int iSite = 0; iSite < num_sites_; ++iSite) {
291 const Arrangement_2::Face_const_handle* f;
292 if ((f = std::get_if<Arrangement_2::Face_const_handle>(&query_results_vor_sorted[iSite].second))) {
293 if((*f)->is_unbounded()) {
294 throw std::runtime_error{
"inside the unbounded face."};
297 throw std::runtime_error{
"Invalid object."};
301 typename Arrangement_2::Ccb_halfedge_const_circulator circ =
303 typename Arrangement_2::Ccb_halfedge_const_circulator curr = circ;
304 auto curr_pt = curr->source()->point();
307 curr_pt = he->target()->point();
308 polygon.push_back(curr_pt);
310 }
while (curr != circ);
312 if (polygon.size() == 0) {
313 throw std::runtime_error{
"Zero size polygon"};
320 vcell.
cell.reserve(polygon.size());
321 for (
auto const &p : polygon) {
324 ComputeMassCentroid(vcell);
325 voronoi_cells_[iSite] = vcell;
void ComputeVoronoiCells()
Contains the configuration for the CGAL library.
CGAL::Arrangement_2< Traits_2 > Arrangement_2
CGAL::Polygon_2< K > Polygon_2
std::pair< CGAL_Point2, CGAL_Point_location_result::Type > CGAL_Query_result
CGAL::Delaunay_triangulation_2< K > Delaunay_triangulation_2
Constants for the CoverageControl library.
std::vector< Point2 > PointVector
Namespace for the CoverageControl library.
void CGAL_CCBTraversal(typename Arrangement::Ccb_halfedge_const_circulator circ, Polygon_2 &polygon)
Point2 CGALtoCC(CGAL_Point2 const pt)
std::vector< Ray_2 > rays_
std::vector< Line_2 > lines_
std::vector< Segment_2 > segments_
void ComputeFinalCentroid()
void MassCentroidFunctional(double const &map_val, Point2 pt)
Contains utility functions for CGAL.
Class for computing Voronoi cells.