mirror of https://github.com/CGAL/cgal
Interception sweep for do_intersect()
This commit is contained in:
parent
a366725c85
commit
f69ad03ef8
|
|
@ -7,12 +7,11 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GPS_AGG_META_TRAITS_H
|
||||
#define CGAL_BSO_2_GPS_AGG_META_TRAITS_H
|
||||
#ifndef CGAL_GPS_AGG_META_TRAITS_H
|
||||
#define CGAL_GPS_AGG_META_TRAITS_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@
|
|||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GPS_AGG_OP_H
|
||||
#define CGAL_BSO_2_GPS_AGG_OP_H
|
||||
#ifndef CGAL_GPS_AGG_OP_H
|
||||
#define CGAL_GPS_AGG_OP_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -19,8 +20,8 @@
|
|||
*
|
||||
* The class Gps_agg_op is responsible for aggregated Boolean set operations
|
||||
* depending on a visitor template parameter. It uses the surface-sweep
|
||||
* algorithm from the arrangement packages to overlay all the polygon sets, and
|
||||
* then it uses a BFS that determines which of the faces is contained in the
|
||||
* algorithm from the surface-sweep package to overlay all the polygon sets, and
|
||||
* then it uses a BFS that determines which of the faces are contained in the
|
||||
* result using the visitor.
|
||||
*/
|
||||
|
||||
|
|
@ -37,7 +38,7 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename Arrangement_, typename BfsVisitor>
|
||||
template <typename Arrangement_, typename BfsVisitor, template <typename, typename> class SweepVisitor>
|
||||
class Gps_agg_op {
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Bfs_visitor = BfsVisitor;
|
||||
|
|
@ -74,7 +75,7 @@ class Gps_agg_op {
|
|||
using Subcurve = Arr_construction_subcurve<Mgt2, Event, Allocator>;
|
||||
using Helper_tmp = typename Tt::template Construction_helper<Event, Subcurve>;
|
||||
using Helper = typename Helper_tmp::template rebind<Mgt2, Arr, Event, Subcurve>::other;
|
||||
using Visitor = Gps_agg_op_visitor<Helper, Arr>;
|
||||
using Visitor = SweepVisitor<Helper, Arr>;
|
||||
using Surface_sweep_2 = Gps_agg_op_surface_sweep_2<Arr, Visitor>;
|
||||
|
||||
using Edges_hash = Unique_hash_map<Halfedge_handle, std::size_t>;
|
||||
|
|
@ -90,7 +91,7 @@ protected:
|
|||
Faces_hash m_faces_hash; // maps face to its IC (inside count)
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
/*! constructs. */
|
||||
Gps_agg_op(Arr& arr, std::vector<Vertex_handle>& vert_vec, const Gt2& tr) :
|
||||
m_arr(&arr),
|
||||
m_traits(new Mgt2(tr)),
|
||||
|
|
@ -98,38 +99,38 @@ public:
|
|||
m_surface_sweep(m_traits, &m_visitor)
|
||||
{}
|
||||
|
||||
void sweep_arrangements(std::size_t lower, std::size_t upper,
|
||||
std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
||||
|
||||
std::size_t prepare(std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec, std::list<Meta_X_monotone_curve_2>& curves_list) {
|
||||
std::size_t n_inf_pgn = 0; // number of infinite polygons (arrangement
|
||||
// with a contained unbounded face
|
||||
std::size_t n_pgn = 0; // number of polygons (arrangements)
|
||||
|
||||
for (std::size_t i = lower; i <= upper; i += jump, ++n_pgn) {
|
||||
for (auto i = lower; i <= upper; i += jump) {
|
||||
// The BFS scan (after the loop) starts in the reference face,
|
||||
// so we count the number of polygons that contain the reference face.
|
||||
Arr* arr = (arr_vec[i]).first;
|
||||
if (arr->reference_face()->contained()) ++n_inf_pgn;
|
||||
|
||||
Edge_iterator itr = arr->edges_begin();
|
||||
for(; itr != arr->edges_end(); ++itr) {
|
||||
for (auto itr = arr->edges_begin(); itr != arr->edges_end(); ++itr) {
|
||||
// take only relevant edges (which separate between contained and
|
||||
// non-contained faces.
|
||||
Halfedge_iterator he = itr;
|
||||
if (he->face()->contained() == he->twin()->face()->contained())
|
||||
continue;
|
||||
if ((Arr_halfedge_direction)he->direction() == ARR_RIGHT_TO_LEFT)
|
||||
he = he->twin();
|
||||
Halfedge_handle he = itr;
|
||||
if (he->face()->contained() == he->twin()->face()->contained()) continue;
|
||||
if ((Arr_halfedge_direction)he->direction() == ARR_RIGHT_TO_LEFT) he = he->twin();
|
||||
|
||||
Curve_data cv_data(arr, he, 1, 0);
|
||||
curves_list.push_back(Meta_X_monotone_curve_2(he->curve(), cv_data));
|
||||
}
|
||||
}
|
||||
return n_inf_pgn;
|
||||
}
|
||||
|
||||
m_surface_sweep.sweep(curves_list.begin(), curves_list.end(),
|
||||
lower, upper, jump, arr_vec);
|
||||
|
||||
/*! sweeps the plane without interceptions.
|
||||
*/
|
||||
void sweep_arrangements(std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec) {
|
||||
std::size_t n_pgn = upper - lower + 1; // number of polygons (arrangements)
|
||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
||||
auto n_inf_pgn = prepare(lower, upper, jump, arr_vec, curves_list);
|
||||
m_surface_sweep.sweep(curves_list.begin(), curves_list.end(), lower, upper, jump, arr_vec);
|
||||
m_faces_hash[m_arr->reference_face()] = n_inf_pgn;
|
||||
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
||||
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
||||
|
|
@ -138,7 +139,26 @@ public:
|
|||
visitor.after_scan(*m_arr);
|
||||
}
|
||||
|
||||
/*! Destruct.
|
||||
/*! sweeps the plane without interceptions, but stop when an intersection occurs.
|
||||
*/
|
||||
bool sweep_intercept_arrangements(std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec) {
|
||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
||||
auto n_inf_pgn = prepare(lower, upper, jump, arr_vec, curves_list);
|
||||
auto res = m_surface_sweep.sweep_intercept(curves_list.begin(), curves_list.end(), lower, upper, jump, arr_vec);
|
||||
if (res) return true;
|
||||
|
||||
m_faces_hash[m_arr->reference_face()] = n_inf_pgn;
|
||||
std::size_t n_pgn = upper - lower + 1; // number of polygons (arrangements)
|
||||
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
||||
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
||||
Bfs_scanner scanner(visitor);
|
||||
scanner.scan(*m_arr);
|
||||
visitor.after_scan(*m_arr);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! destructs.
|
||||
*/
|
||||
~Gps_agg_op() { delete m_traits; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@
|
|||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
#define CGAL_BSO_2_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
#ifndef CGAL_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
#define CGAL_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -70,9 +71,8 @@ public:
|
|||
Base(traits, visitor)
|
||||
{}
|
||||
|
||||
/*! Perform the sweep. */
|
||||
template <typename CurveInputIterator>
|
||||
void sweep(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
void pre_process(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
std::size_t lower, std::size_t upper, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec) {
|
||||
CGAL_assertion(this->m_queue->empty() && this->m_statusLine.size() == 0);
|
||||
|
|
@ -80,7 +80,6 @@ public:
|
|||
using Vertices_map = Unique_hash_map<Vertex_handle, Event*>;
|
||||
using Compare_xy_2 = typename Gt2::Compare_xy_2;
|
||||
|
||||
this->m_visitor->before_sweep();
|
||||
// Allocate all of the Subcurve objects as one block.
|
||||
this->m_num_of_subCurves = std::distance(curves_begin, curves_end);
|
||||
if (this->m_num_of_subCurves > 0)
|
||||
|
|
@ -203,13 +202,29 @@ public:
|
|||
e_right->add_curve_to_left(this->m_subCurves + index);
|
||||
this->_add_curve_to_right(e_left, this->m_subCurves + index);
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the sweep:
|
||||
/*! Perform the sweep. */
|
||||
template <typename CurveInputIterator>
|
||||
void sweep(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
std::size_t lower, std::size_t upper, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
this->m_visitor->before_sweep();
|
||||
pre_process(curves_begin, curves_end,lower, upper, jump, arr_vec);
|
||||
this->_sweep();
|
||||
this->_complete_sweep();
|
||||
this->m_visitor->after_sweep();
|
||||
}
|
||||
|
||||
return;
|
||||
/*! Perform the sweep. */
|
||||
template <typename CurveInputIterator>
|
||||
bool sweep_intercept(CurveInputIterator curves_begin, CurveInputIterator curves_end,
|
||||
std::size_t lower, std::size_t upper, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
this->m_visitor->before_sweep();
|
||||
pre_process(curves_begin, curves_end,lower, upper, jump, arr_vec);
|
||||
this->_sweep();
|
||||
this->_complete_sweep();
|
||||
this->m_visitor->after_sweep();
|
||||
return this->m_visitor->found_intersection();
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -230,7 +245,6 @@ private:
|
|||
else return (Event::LEFT_END);
|
||||
}
|
||||
++circ;
|
||||
|
||||
} while (circ != first);
|
||||
|
||||
// If we reached here, we should not keep this vertex.
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ron Wein <wein@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_BSO_2_GSP_AGG_OP_VISITOR_H
|
||||
#define CGAL_BSO_2_GSP_AGG_OP_VISITOR_H
|
||||
#ifndef CGAL_GSP_AGG_OP_VISITOR_H
|
||||
#define CGAL_GSP_AGG_OP_VISITOR_H
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ class Gps_agg_op_base_visitor :
|
|||
Helper_,
|
||||
typename Default::Get<Visitor_, Gps_agg_op_base_visitor<Helper_,
|
||||
Arrangement_,
|
||||
Visitor_> >::type> {
|
||||
Visitor_>>::type> {
|
||||
public:
|
||||
using Helper = Helper_;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
|
|
@ -43,7 +43,6 @@ public:
|
|||
private:
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Arr = Arrangement_2;
|
||||
|
||||
using Self = Gps_agg_op_base_visitor<Helper, Arr, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Arr_construction_ss_visitor<Helper, Visitor>;
|
||||
|
|
@ -127,7 +126,8 @@ template <typename Helper_, typename Arrangement_, typename Visitor_ = Default>
|
|||
class Gps_agg_op_visitor :
|
||||
public Gps_agg_op_base_visitor<
|
||||
Helper_, Arrangement_,
|
||||
Gps_agg_op_visitor<Helper_, Arrangement_, Visitor_>> {
|
||||
typename Default::Get<Visitor_,
|
||||
Gps_agg_op_visitor<Helper_, Arrangement_, Visitor_>>::type> {
|
||||
public:
|
||||
using Helper = Helper_;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
|
|
@ -145,6 +145,7 @@ private:
|
|||
using Base = Gps_agg_op_base_visitor<Helper, Arr, Visitor>;
|
||||
|
||||
public:
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Halfedge_handle = typename Base::Halfedge_handle;
|
||||
using Vertex_handle = typename Base::Vertex_handle;
|
||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||
|
|
@ -156,7 +157,7 @@ protected:
|
|||
// ascending order.
|
||||
|
||||
public:
|
||||
Gps_agg_op_visitor(Arr* arr, typename Base::Edges_hash* hash,
|
||||
Gps_agg_op_visitor(Arr* arr, Edges_hash* hash,
|
||||
std::vector<Vertex_handle>* vertices_vec) :
|
||||
Base(arr, hash),
|
||||
m_event_count(0),
|
||||
|
|
@ -210,7 +211,7 @@ public:
|
|||
|
||||
CGAL_assertion((Arr_halfedge_direction)res_he->direction() ==
|
||||
ARR_LEFT_TO_RIGHT);
|
||||
_insert_vertex (curr_event, res_he->target());
|
||||
_insert_vertex(curr_event, res_he->target());
|
||||
return res_he;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ protected:
|
|||
std::size_t m_num_of_polygons; // number of polygons
|
||||
|
||||
public:
|
||||
|
||||
Gps_bfs_base_visitor(Edges_hash* edges_hash,
|
||||
Faces_hash* faces_hash,
|
||||
std::size_t n_pgn):
|
||||
|
|
@ -84,7 +83,7 @@ protected:
|
|||
CGAL_assertion(m_edges_hash->is_defined(he) &&
|
||||
m_edges_hash->is_defined(he->twin()) &&
|
||||
m_faces_hash->is_defined(f1) &&
|
||||
!m_faces_hash->is_defined(f2));
|
||||
! m_faces_hash->is_defined(f2));
|
||||
std::size_t ic_f2 =
|
||||
(*m_faces_hash)[f1] - (*m_edges_hash)[he] + (*m_edges_hash)[he->twin()];
|
||||
(*m_faces_hash)[f2] = ic_f2;
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@
|
|||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
||||
#define CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) 2005 Tel-Aviv University (Israel).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GSP_DO_INTERSECT_AGG_OP_VISITOR_H
|
||||
#define CGAL_GSP_DO_INTERSECT_AGG_OP_VISITOR_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_op_visitor.h>
|
||||
#include <CGAL/Default.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename Helper_, typename Arrangement_, typename Visitor_ = Default>
|
||||
class Gps_do_intersect_agg_op_visitor :
|
||||
public Gps_agg_op_visitor<
|
||||
Helper_, Arrangement_,
|
||||
typename Default::Get<Visitor_, Gps_do_intersect_agg_op_visitor<Helper_, Arrangement_, Visitor_>>::type> {
|
||||
public:
|
||||
using Helper = Helper_;
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Geometry_traits_2 = typename Helper::Geometry_traits_2;
|
||||
using Event = typename Helper::Event;
|
||||
using Subcurve = typename Helper::Subcurve;
|
||||
|
||||
private:
|
||||
using Gt2 = Geometry_traits_2;
|
||||
using Arr = Arrangement_2;
|
||||
using Self = Gps_do_intersect_agg_op_visitor<Helper, Arr, Visitor_>;
|
||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||
using Base = Gps_agg_op_visitor<Helper, Arr, Visitor>;
|
||||
|
||||
protected:
|
||||
bool m_found_x;
|
||||
|
||||
public:
|
||||
using Edges_hash = typename Base::Edges_hash;
|
||||
using Vertex_handle = typename Base::Vertex_handle;
|
||||
using Status_line_iterator = typename Base::Status_line_iterator;
|
||||
using X_monotone_curve_2 = typename Base::X_monotone_curve_2;
|
||||
using Point_2 = typename Base::Point_2;
|
||||
|
||||
Gps_do_intersect_agg_op_visitor(Arr* arr, Edges_hash* hash,
|
||||
std::vector<Vertex_handle>* vertices_vec) :
|
||||
Base(arr, hash, vertices_vec),
|
||||
m_found_x(false)
|
||||
{}
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint. */
|
||||
void update_event(Event* e, const Point_2& end_point, const X_monotone_curve_2& cv, Arr_curve_end cv_end, bool is_new)
|
||||
{ return Base::update_event(e, end_point, cv, cv_end, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint */
|
||||
void update_event(Event* e, const X_monotone_curve_2& cv, Arr_curve_end cv_end, bool is_new )
|
||||
{ return Base::update_event(e, cv, cv_end, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to a curve endpoint */
|
||||
void update_event(Event* e, const Point_2& p, bool is_new)
|
||||
{ return Base::update_event(e, p, is_new); }
|
||||
|
||||
/*! Update an event that corresponds to an intersection */
|
||||
void update_event(Event* e, Subcurve* sc) { return Base::update_event(e, sc); }
|
||||
|
||||
/*! Update an event that corresponds to an intersection between curves */
|
||||
void update_event(Event*, Subcurve*, Subcurve*, bool is_new) { m_found_x = true; }
|
||||
|
||||
bool after_handle_event(Event* e, Status_line_iterator iter, bool flag) {
|
||||
auto res = Base::after_handle_event(e, iter, flag);
|
||||
if (m_found_x) this->surface_sweep()->stop_sweep();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! Getter */
|
||||
bool found_intersection() { return m_found_x; }
|
||||
};
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GPS_MERGE_H
|
||||
#define CGAL_GPS_MERGE_H
|
||||
|
|
@ -15,6 +16,8 @@
|
|||
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_op.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_agg_op_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_do_intersect_agg_op_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_join_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_xor_visitor.h>
|
||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_intersection_visitor.h>
|
||||
|
|
@ -23,16 +26,16 @@
|
|||
namespace CGAL {
|
||||
|
||||
/*! \file Gps_merge.h
|
||||
* \brief This file contains classes that are responsible for merging
|
||||
* two sets of polygons in the divide-and-conquer algorithm.
|
||||
* The file contains 3 mergers: Join_merge, Intersection_merge and
|
||||
* Xor_merge. Join_merge is used when we want to merge the two sets,
|
||||
* Intersection_merge is used for intersection, and Xor_merge is used
|
||||
* for symmetric difference.
|
||||
*
|
||||
* This file contains classes that are responsible for merging two sets of
|
||||
* polygons in the divide-and-conquer algorithm. The file contains 3 mergers:
|
||||
* Join_merge, Intersection_merge and Xor_merge. Join_merge is used when we want
|
||||
* to merge the two sets, Intersection_merge is used for intersection, and
|
||||
* Xor_merge is used for symmetric difference.
|
||||
*/
|
||||
|
||||
//! Base_merge
|
||||
/*! Base_merge is the base class for all merger classes.
|
||||
/*! Base_merge
|
||||
* Base_merge is the base class for all merger classes.
|
||||
* All merges used BFS algorithm with a different visitor when discovering
|
||||
* a new face.
|
||||
*/
|
||||
|
|
@ -44,17 +47,15 @@ class Base_merge {
|
|||
using Arr_entry = std::pair<Arrangement_2*, std::vector<Vertex_handle>*>;
|
||||
|
||||
public:
|
||||
void operator()(std::size_t i, std::size_t j, std::size_t jump,
|
||||
std::vector<Arr_entry>& arr_vec) {
|
||||
void operator()(std::size_t i, std::size_t j, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
if (i == j) return;
|
||||
|
||||
const typename Arrangement_2::Geometry_traits_2* tr =
|
||||
arr_vec[i].first->geometry_traits();
|
||||
const auto* tr = arr_vec[i].first->geometry_traits();
|
||||
Arrangement_2* res = new Arrangement_2(tr);
|
||||
std::vector<Vertex_handle>* verts = new std::vector<Vertex_handle>;
|
||||
|
||||
Gps_agg_op<Arrangement_2, Visitor>
|
||||
agg_op(*res, *verts, *(res->traits_adaptor()));
|
||||
using Agg_op = Gps_agg_op<Arrangement_2, Visitor, Gps_agg_op_visitor>;
|
||||
Agg_op agg_op(*res, *verts, *(res->traits_adaptor()));
|
||||
agg_op.sweep_arrangements(i, j, jump, arr_vec);
|
||||
|
||||
for (std::size_t count = i; count <= j; count += jump) {
|
||||
|
|
@ -67,29 +68,69 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
//! Join_merge
|
||||
/*! Join_merge is used to join two sets of polygons together in the D&C
|
||||
/*! Base_intercepted_merge
|
||||
* Base_intercepted_merge is the base class for all merger classes that can be
|
||||
* interceted (e.g., when an intersection is detected). All merges used BFS
|
||||
* algorithm with a different visitor when discovering a new face.
|
||||
*/
|
||||
template <typename Arrangement_, typename Visitor_>
|
||||
class Base_intercepted_merge {
|
||||
using Arrangement_2 = Arrangement_;
|
||||
using Visitor = Visitor_;
|
||||
using Vertex_handle = typename Arrangement_2::Vertex_handle;
|
||||
using Arr_entry = std::pair<Arrangement_2*, std::vector<Vertex_handle>*>;
|
||||
|
||||
public:
|
||||
bool operator()(std::size_t i, std::size_t j, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||
if (i == j) return false;
|
||||
|
||||
const auto* tr = arr_vec[i].first->geometry_traits();
|
||||
Arrangement_2* arr = new Arrangement_2(tr);
|
||||
std::vector<Vertex_handle>* verts = new std::vector<Vertex_handle>;
|
||||
|
||||
using Agg_op = Gps_agg_op<Arrangement_2, Visitor, Gps_do_intersect_agg_op_visitor>;
|
||||
Agg_op agg_op(*arr, *verts, *(arr->traits_adaptor()));
|
||||
auto res = agg_op.sweep_intercept_arrangements(i, j, jump, arr_vec);
|
||||
|
||||
for (auto count = i; count <= j; count += jump) {
|
||||
delete (arr_vec[count].first);
|
||||
delete (arr_vec[count].second);
|
||||
}
|
||||
|
||||
arr_vec[i].first = arr;
|
||||
arr_vec[i].second = verts;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
/*! Join_merge
|
||||
* Join_merge is used to join two sets of polygons together in the D&C
|
||||
* algorithm. It is a base merge with a visitor that joins faces.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Join_merge : public Base_merge<Arrangement_, Gps_bfs_join_visitor<Arrangement_>>
|
||||
{};
|
||||
class Join_merge : public Base_merge<Arrangement_, Gps_bfs_join_visitor<Arrangement_>>{};
|
||||
|
||||
//! Intersection_merge
|
||||
/*! Intersection_merge is used to merge two sets of polygons creating their
|
||||
/*! Intersection_merge
|
||||
* Intersection_merge is used to merge two sets of polygons creating their
|
||||
* intersection.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Intersection_merge : public Base_merge<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_>>
|
||||
{};
|
||||
class Intersection_merge : public Base_merge<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_>>{};
|
||||
|
||||
//! Xor_merge
|
||||
/*! Xor_merge is used to merge two sets of polygons creating their
|
||||
/*! Do_intersect_merge
|
||||
* Do_intersect_merge is used to merge two sets of polygons creating their
|
||||
* intersection. When an intersection in the interior of the boundary curves
|
||||
* is detected, the sweep is intercepted.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Do_intersect_merge : public Base_intercepted_merge<Arrangement_, Gps_bfs_intersection_visitor<Arrangement_>>{};
|
||||
|
||||
/*! Xor_merge
|
||||
* Xor_merge is used to merge two sets of polygons creating their
|
||||
* symmetric difference.
|
||||
*/
|
||||
template <typename Arrangement_>
|
||||
class Xor_merge : public Base_merge<Arrangement_, Gps_bfs_xor_visitor<Arrangement_>>
|
||||
{};
|
||||
class Xor_merge : public Base_merge<Arrangement_, Gps_bfs_xor_visitor<Arrangement_>>{};
|
||||
|
||||
} //namespace CGAL
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||
// Guy Zucker <guyzucke@post.tau.ac.il>
|
||||
|
||||
// Efi Fogel <efifogel@gmail.com>
|
||||
|
||||
#ifndef CGAL_GPS_ON_SURFACE_BASE_2_H
|
||||
#define CGAL_GPS_ON_SURFACE_BASE_2_H
|
||||
|
|
@ -388,7 +388,6 @@ public:
|
|||
|
||||
const Traits_2& traits() const { return *m_traits; }
|
||||
|
||||
bool is_empty() const {
|
||||
// We have to check that all the faces of an empty arrangement are not
|
||||
// contained in the polygon set (there can be several faces in an empty
|
||||
// arrangement, dependent on the topology traits.
|
||||
|
|
@ -398,8 +397,10 @@ public:
|
|||
// result for contained() --- from Boolean operations point of view there
|
||||
// can not be an empty arrangement which has several faces with different
|
||||
// attributes.
|
||||
return (m_arr->is_empty() && !m_arr->faces_begin()->contained());
|
||||
}
|
||||
bool is_empty() const { this->_is_empty(m_arr); }
|
||||
|
||||
bool _is_empty(Aos_2* arr) const
|
||||
{ return (arr->is_empty() && ! arr->faces_begin()->contained()); }
|
||||
|
||||
bool is_plane() const {
|
||||
// Same comment as in "is_empty" above, just with adjustments.
|
||||
|
|
@ -493,8 +494,33 @@ public:
|
|||
template <typename InputIterator>
|
||||
bool do_intersect(InputIterator begin, InputIterator end, std::size_t k = 5) {
|
||||
Self other(*this);
|
||||
other.intersection(begin, end, k);
|
||||
return (other.is_empty());
|
||||
return other._do_intersect(begin, end, k);
|
||||
}
|
||||
|
||||
// intersects a range of polygons
|
||||
template <typename InputIterator>
|
||||
inline bool _do_intersect(InputIterator begin, InputIterator end, std::size_t k) {
|
||||
std::vector<Arr_entry> arr_vec(std::distance(begin, end) + 1);
|
||||
arr_vec[0].first = this->m_arr;
|
||||
std::size_t i = 1;
|
||||
|
||||
for (auto it = begin; it != end; ++it, ++i) {
|
||||
ValidationPolicy::is_valid((*it), *m_traits);
|
||||
arr_vec[i].first = new Aos_2(m_traits);
|
||||
_insert(*it, *(arr_vec[i].first));
|
||||
}
|
||||
|
||||
Do_intersect_merge<Aos_2> do_intersect_merge;
|
||||
auto res = do_intersect_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, do_intersect_merge);
|
||||
|
||||
// The resulting arrangement is at index 0
|
||||
this->m_arr = arr_vec[0].first;
|
||||
delete arr_vec[0].second;
|
||||
if (res) return res;
|
||||
|
||||
_remove_redundant_edges(arr_vec[0].first);
|
||||
_reset_faces(arr_vec[0].first);
|
||||
return (_is_empty(arr_vec[0].first));
|
||||
}
|
||||
|
||||
template <typename InputIterator1, typename InputIterator2>
|
||||
|
|
@ -502,8 +528,40 @@ public:
|
|||
InputIterator2 begin2, InputIterator2 end2,
|
||||
std::size_t k = 5) {
|
||||
Self other(*this);
|
||||
other.intersection(begin1, end1, begin2, end2, k);
|
||||
return (other.is_empty());
|
||||
return other._do_intersect(begin1, end1, begin2, end2, k);
|
||||
}
|
||||
|
||||
template <typename InputIterator1, typename InputIterator2>
|
||||
bool _do_intersect(InputIterator1 begin1, InputIterator1 end1,
|
||||
InputIterator2 begin2, InputIterator2 end2,
|
||||
std::size_t k = 5) {
|
||||
std::vector<Arr_entry> arr_vec(std::distance(begin1, end1) + std::distance(begin2, end2) + 1);
|
||||
arr_vec[0].first = this->m_arr;
|
||||
std::size_t i = 1;
|
||||
|
||||
for (InputIterator1 itr1 = begin1; itr1 != end1; ++itr1, ++i) {
|
||||
ValidationPolicy::is_valid(*itr1, *m_traits);
|
||||
arr_vec[i].first = new Aos_2(m_traits);
|
||||
_insert(*itr1, *(arr_vec[i].first));
|
||||
}
|
||||
|
||||
for (InputIterator2 itr2 = begin2; itr2 != end2; ++itr2, ++i) {
|
||||
ValidationPolicy::is_valid(*itr2,*m_traits);
|
||||
arr_vec[i].first = new Aos_2(m_traits);
|
||||
_insert(*itr2, *(arr_vec[i].first));
|
||||
}
|
||||
|
||||
Do_intersect_merge<Aos_2> do_intersect_merge;
|
||||
auto res = do_intersect_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, do_intersect_merge);
|
||||
|
||||
// The resulting arrangement is at index 0
|
||||
this->m_arr = arr_vec[0].first;
|
||||
delete arr_vec[0].second;
|
||||
if (res) return res;
|
||||
|
||||
_remove_redundant_edges(arr_vec[0].first);
|
||||
_reset_faces(arr_vec[0].first);
|
||||
return (_is_empty(arr_vec[0].first));
|
||||
}
|
||||
|
||||
// joins a range of polygons
|
||||
|
|
@ -533,7 +591,6 @@ public:
|
|||
}
|
||||
|
||||
Join_merge<Aos_2> join_merge;
|
||||
_build_sorted_vertices_vectors(arr_vec);
|
||||
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, join_merge);
|
||||
|
||||
//the result arrangement is at index 0
|
||||
|
|
@ -556,7 +613,6 @@ public:
|
|||
}
|
||||
|
||||
Join_merge<Aos_2> join_merge;
|
||||
_build_sorted_vertices_vectors(arr_vec);
|
||||
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, join_merge);
|
||||
|
||||
// the result arrangement is at index 0
|
||||
|
|
@ -585,7 +641,6 @@ public:
|
|||
}
|
||||
|
||||
Join_merge<Aos_2> join_merge;
|
||||
_build_sorted_vertices_vectors(arr_vec);
|
||||
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, join_merge);
|
||||
|
||||
// the result arrangement is at index 0
|
||||
|
|
@ -620,7 +675,6 @@ public:
|
|||
}
|
||||
|
||||
Intersection_merge<Aos_2> intersection_merge;
|
||||
_build_sorted_vertices_vectors(arr_vec);
|
||||
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, intersection_merge);
|
||||
|
||||
// the result arrangement is at index 0
|
||||
|
|
@ -636,14 +690,13 @@ public:
|
|||
arr_vec[0].first = this->m_arr;
|
||||
std::size_t i = 1;
|
||||
|
||||
for (InputIterator itr = begin; itr!=end; ++itr, ++i) {
|
||||
for (InputIterator itr = begin; itr != end; ++itr, ++i) {
|
||||
ValidationPolicy::is_valid((*itr), *m_traits);
|
||||
arr_vec[i].first = new Aos_2(m_traits);
|
||||
_insert(*itr, *(arr_vec[i].first));
|
||||
}
|
||||
|
||||
Intersection_merge<Aos_2> intersection_merge;
|
||||
_build_sorted_vertices_vectors(arr_vec);
|
||||
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, intersection_merge);
|
||||
|
||||
// the result arrangement is at index 0
|
||||
|
|
@ -659,20 +712,19 @@ public:
|
|||
arr_vec[0].first = this->m_arr;
|
||||
std::size_t i = 1;
|
||||
|
||||
for (InputIterator1 itr1 = begin1; itr1!=end1; ++itr1, ++i) {
|
||||
for (InputIterator1 itr1 = begin1; itr1 != end1; ++itr1, ++i) {
|
||||
ValidationPolicy::is_valid(*itr1, *m_traits);
|
||||
arr_vec[i].first = new Aos_2(m_traits);
|
||||
_insert(*itr1, *(arr_vec[i].first));
|
||||
}
|
||||
|
||||
for (InputIterator2 itr2 = begin2; itr2!=end2; ++itr2, ++i) {
|
||||
for (InputIterator2 itr2 = begin2; itr2 != end2; ++itr2, ++i) {
|
||||
ValidationPolicy::is_valid(*itr2,*m_traits);
|
||||
arr_vec[i].first = new Aos_2(m_traits);
|
||||
_insert(*itr2, *(arr_vec[i].first));
|
||||
}
|
||||
|
||||
Intersection_merge<Aos_2> intersection_merge;
|
||||
_build_sorted_vertices_vectors(arr_vec);
|
||||
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, intersection_merge);
|
||||
|
||||
// the result arrangement is at index 0
|
||||
|
|
@ -708,7 +760,6 @@ public:
|
|||
}
|
||||
|
||||
Xor_merge<Aos_2> xor_merge;
|
||||
_build_sorted_vertices_vectors(arr_vec);
|
||||
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, xor_merge);
|
||||
|
||||
// the result arrangement is at index 0
|
||||
|
|
@ -731,7 +782,6 @@ public:
|
|||
}
|
||||
|
||||
Xor_merge<Aos_2> xor_merge;
|
||||
_build_sorted_vertices_vectors(arr_vec);
|
||||
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, xor_merge);
|
||||
|
||||
// the result arrangement is at index 0
|
||||
|
|
@ -761,7 +811,6 @@ public:
|
|||
}
|
||||
|
||||
Xor_merge<Aos_2> xor_merge;
|
||||
_build_sorted_vertices_vectors(arr_vec);
|
||||
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, xor_merge);
|
||||
|
||||
// the result arrangement is at index 0
|
||||
|
|
@ -1155,10 +1204,10 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
void _build_sorted_vertices_vectors(std::vector<Arr_entry>& arr_vec) {
|
||||
//! Allocate, collect , and sort the vertex handles of the arrangements in the given interval
|
||||
void _build_sorted_vertices_vectors(std::size_t lower, std::size_t upper, std::vector<Arr_entry>& arr_vec) {
|
||||
Less_vertex_handle comp(m_traits->compare_xy_2_object());
|
||||
const std::size_t n = arr_vec.size();
|
||||
for (std::size_t i = 0; i < n; i++) {
|
||||
for (std::size_t i = lower; i < upper + 1; i++) {
|
||||
// Allocate a vector of handles to all vertices in the current arrangement.
|
||||
Aos_2* p_arr = arr_vec[i].first;
|
||||
arr_vec[i].second = new std::vector<Vertex_handle>;
|
||||
|
|
@ -1174,11 +1223,16 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
//! Divide & conquer
|
||||
template <typename Merge>
|
||||
void _divide_and_conquer(std::size_t lower, std::size_t upper,
|
||||
std::vector<Arr_entry>& arr_vec,
|
||||
std::size_t k, Merge merge_func) {
|
||||
static int indent = 0;
|
||||
std::cout << std::setw(indent) << "" << "D&C [" << lower << "," << upper << "," << k << "]\n";
|
||||
if ((upper - lower) < k) {
|
||||
std::cout << std::setw(indent) << "" << "Merging [" << lower << "," << upper << "," << 1 << "]\n";
|
||||
_build_sorted_vertices_vectors(lower, upper, arr_vec);
|
||||
merge_func(lower, upper, 1, arr_vec);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1187,12 +1241,71 @@ protected:
|
|||
auto curr_lower = lower;
|
||||
|
||||
for (std::size_t i = 0; i < k - 1; ++i, curr_lower += sub_size) {
|
||||
indent += 2;
|
||||
_divide_and_conquer(curr_lower, curr_lower + sub_size-1, arr_vec, k, merge_func);
|
||||
indent -= 2;
|
||||
}
|
||||
indent += 2;
|
||||
_divide_and_conquer(curr_lower, upper, arr_vec, k, merge_func);
|
||||
indent -= 2;
|
||||
std::cout << std::setw(indent) << "" << "Merging [" << lower << "," << curr_lower << "," << sub_size << "]\n";
|
||||
merge_func(lower, curr_lower, sub_size, arr_vec);
|
||||
}
|
||||
|
||||
/*! Divide & conquer tailored for the do_intersect() function.
|
||||
* It returns a Boolean value indicating whether an intersection in the
|
||||
* interiors of the curves have been detected. Also, it terminates
|
||||
* as a sson as such an intersection has been detected.
|
||||
*/
|
||||
template <typename Merge>
|
||||
bool do_intersect_divide_and_conquer(std::size_t lower, std::size_t upper,
|
||||
std::vector<Arr_entry>& arr_vec,
|
||||
std::size_t k, Merge merge_func) {
|
||||
static int indent = 0;
|
||||
std::cout << std::setw(indent) << "" << "D&C [" << lower << "," << upper << "," << k << "]\n";
|
||||
if ((upper - lower) < k) {
|
||||
std::cout << std::setw(indent) << "" << "Merging [" << lower << "," << upper << "," << 1 << "]\n";
|
||||
_build_sorted_vertices_vectors(lower, upper, arr_vec);
|
||||
return merge_func(lower, upper, 1, arr_vec);
|
||||
}
|
||||
|
||||
auto sub_size = ((upper - lower + 1) / k);
|
||||
auto curr_lower = lower;
|
||||
|
||||
bool res = false;
|
||||
for (std::size_t i = 0; i < k - 1; ++i, curr_lower += sub_size) {
|
||||
indent += 2;
|
||||
res = do_intersect_divide_and_conquer(curr_lower, curr_lower + sub_size-1, arr_vec, k, merge_func);
|
||||
indent -= 2;
|
||||
if (res) break;
|
||||
}
|
||||
if (res) {
|
||||
// Clean up the entries that have been created
|
||||
std::cout << std::setw(indent) << "" << "Cleaning [" << lower + sub_size << "," << curr_lower << "," << sub_size << "]\n";
|
||||
for (auto count = lower + sub_size; count <= curr_lower; count += sub_size) {
|
||||
delete (arr_vec[count].first);
|
||||
delete (arr_vec[count].second);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
indent += 2;
|
||||
res = do_intersect_divide_and_conquer(curr_lower, upper, arr_vec, k, merge_func);
|
||||
indent -= 2;
|
||||
if (res) {
|
||||
// Clean up the entries that have been created
|
||||
std::cout << std::setw(indent) << "" << "Cleaning [" << lower + sub_size << "," << curr_lower << "," << sub_size << "]\n";
|
||||
for (std::size_t count = lower + sub_size; count <= curr_lower; count += sub_size) {
|
||||
delete (arr_vec[count].first);
|
||||
delete (arr_vec[count].second);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::cout << std::setw(indent) << "" << "Merging [" << lower << "," << curr_lower << "," << sub_size << "]\n";
|
||||
return merge_func(lower, curr_lower, sub_size, arr_vec);
|
||||
}
|
||||
|
||||
// marks all faces as non-visited
|
||||
void _reset_faces() const { _reset_faces(m_arr); }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue