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$
|
// $Id$
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
// Efi Fogel <efifogel@gmail.com>
|
// Efi Fogel <efifogel@gmail.com>
|
||||||
|
|
||||||
#ifndef CGAL_BSO_2_GPS_AGG_META_TRAITS_H
|
#ifndef CGAL_GPS_AGG_META_TRAITS_H
|
||||||
#define CGAL_BSO_2_GPS_AGG_META_TRAITS_H
|
#define CGAL_GPS_AGG_META_TRAITS_H
|
||||||
|
|
||||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,12 @@
|
||||||
// $Id$
|
// $Id$
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
//
|
//
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||||
|
// Efi Fogel <efifogel@gmail.com>
|
||||||
|
|
||||||
#ifndef CGAL_BSO_2_GPS_AGG_OP_H
|
#ifndef CGAL_GPS_AGG_OP_H
|
||||||
#define CGAL_BSO_2_GPS_AGG_OP_H
|
#define CGAL_GPS_AGG_OP_H
|
||||||
|
|
||||||
#include <CGAL/license/Boolean_set_operations_2.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
|
* The class Gps_agg_op is responsible for aggregated Boolean set operations
|
||||||
* depending on a visitor template parameter. It uses the surface-sweep
|
* depending on a visitor template parameter. It uses the surface-sweep
|
||||||
* algorithm from the arrangement packages to overlay all the polygon sets, and
|
* algorithm from the surface-sweep package to overlay all the polygon sets, and
|
||||||
* then it uses a BFS that determines which of the faces is contained in the
|
* then it uses a BFS that determines which of the faces are contained in the
|
||||||
* result using the visitor.
|
* result using the visitor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -37,7 +38,7 @@
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
template <typename Arrangement_, typename BfsVisitor>
|
template <typename Arrangement_, typename BfsVisitor, template <typename, typename> class SweepVisitor>
|
||||||
class Gps_agg_op {
|
class Gps_agg_op {
|
||||||
using Arrangement_2 = Arrangement_;
|
using Arrangement_2 = Arrangement_;
|
||||||
using Bfs_visitor = BfsVisitor;
|
using Bfs_visitor = BfsVisitor;
|
||||||
|
|
@ -74,7 +75,7 @@ class Gps_agg_op {
|
||||||
using Subcurve = Arr_construction_subcurve<Mgt2, Event, Allocator>;
|
using Subcurve = Arr_construction_subcurve<Mgt2, Event, Allocator>;
|
||||||
using Helper_tmp = typename Tt::template Construction_helper<Event, Subcurve>;
|
using Helper_tmp = typename Tt::template Construction_helper<Event, Subcurve>;
|
||||||
using Helper = typename Helper_tmp::template rebind<Mgt2, Arr, Event, Subcurve>::other;
|
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 Surface_sweep_2 = Gps_agg_op_surface_sweep_2<Arr, Visitor>;
|
||||||
|
|
||||||
using Edges_hash = Unique_hash_map<Halfedge_handle, std::size_t>;
|
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)
|
Faces_hash m_faces_hash; // maps face to its IC (inside count)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*! Constructor. */
|
/*! constructs. */
|
||||||
Gps_agg_op(Arr& arr, std::vector<Vertex_handle>& vert_vec, const Gt2& tr) :
|
Gps_agg_op(Arr& arr, std::vector<Vertex_handle>& vert_vec, const Gt2& tr) :
|
||||||
m_arr(&arr),
|
m_arr(&arr),
|
||||||
m_traits(new Mgt2(tr)),
|
m_traits(new Mgt2(tr)),
|
||||||
|
|
@ -98,38 +99,38 @@ public:
|
||||||
m_surface_sweep(m_traits, &m_visitor)
|
m_surface_sweep(m_traits, &m_visitor)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void sweep_arrangements(std::size_t lower, std::size_t upper,
|
std::size_t prepare(std::size_t lower, std::size_t upper, std::size_t jump,
|
||||||
std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
std::vector<Arr_entry>& arr_vec, std::list<Meta_X_monotone_curve_2>& curves_list) {
|
||||||
std::list<Meta_X_monotone_curve_2> curves_list;
|
|
||||||
|
|
||||||
std::size_t n_inf_pgn = 0; // number of infinite polygons (arrangement
|
std::size_t n_inf_pgn = 0; // number of infinite polygons (arrangement
|
||||||
// with a contained unbounded face
|
// with a contained unbounded face
|
||||||
std::size_t n_pgn = 0; // number of polygons (arrangements)
|
for (auto i = lower; i <= upper; i += jump) {
|
||||||
|
|
||||||
for (std::size_t i = lower; i <= upper; i += jump, ++n_pgn) {
|
|
||||||
// The BFS scan (after the loop) starts in the reference face,
|
// The BFS scan (after the loop) starts in the reference face,
|
||||||
// so we count the number of polygons that contain the reference face.
|
// so we count the number of polygons that contain the reference face.
|
||||||
Arr* arr = (arr_vec[i]).first;
|
Arr* arr = (arr_vec[i]).first;
|
||||||
if (arr->reference_face()->contained()) ++n_inf_pgn;
|
if (arr->reference_face()->contained()) ++n_inf_pgn;
|
||||||
|
|
||||||
Edge_iterator itr = arr->edges_begin();
|
for (auto itr = arr->edges_begin(); itr != arr->edges_end(); ++itr) {
|
||||||
for(; itr != arr->edges_end(); ++itr) {
|
|
||||||
// take only relevant edges (which separate between contained and
|
// take only relevant edges (which separate between contained and
|
||||||
// non-contained faces.
|
// non-contained faces.
|
||||||
Halfedge_iterator he = itr;
|
Halfedge_handle he = itr;
|
||||||
if (he->face()->contained() == he->twin()->face()->contained())
|
if (he->face()->contained() == he->twin()->face()->contained()) continue;
|
||||||
continue;
|
if ((Arr_halfedge_direction)he->direction() == ARR_RIGHT_TO_LEFT) he = he->twin();
|
||||||
if ((Arr_halfedge_direction)he->direction() == ARR_RIGHT_TO_LEFT)
|
|
||||||
he = he->twin();
|
|
||||||
|
|
||||||
Curve_data cv_data(arr, he, 1, 0);
|
Curve_data cv_data(arr, he, 1, 0);
|
||||||
curves_list.push_back(Meta_X_monotone_curve_2(he->curve(), cv_data));
|
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(),
|
/*! sweeps the plane without interceptions.
|
||||||
lower, upper, jump, arr_vec);
|
*/
|
||||||
|
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;
|
m_faces_hash[m_arr->reference_face()] = n_inf_pgn;
|
||||||
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
Bfs_visitor visitor(&m_edges_hash, &m_faces_hash, n_pgn);
|
||||||
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
visitor.visit_ubf(m_arr->faces_begin(), n_inf_pgn);
|
||||||
|
|
@ -138,7 +139,26 @@ public:
|
||||||
visitor.after_scan(*m_arr);
|
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; }
|
~Gps_agg_op() { delete m_traits; }
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,12 @@
|
||||||
// $Id$
|
// $Id$
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
//
|
//
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
// Ron Wein <wein@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
|
#ifndef CGAL_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||||
#define CGAL_BSO_2_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
#define CGAL_GSP_AGG_OP_SURFACE_SWEEP_2_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -70,17 +71,15 @@ public:
|
||||||
Base(traits, visitor)
|
Base(traits, visitor)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*! Perform the sweep. */
|
|
||||||
template <typename CurveInputIterator>
|
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::size_t lower, std::size_t upper, std::size_t jump,
|
||||||
std::vector<Arr_entry>& arr_vec) {
|
std::vector<Arr_entry>& arr_vec) {
|
||||||
CGAL_assertion(this->m_queue->empty() && this->m_statusLine.size() == 0);
|
CGAL_assertion(this->m_queue->empty() && this->m_statusLine.size() == 0);
|
||||||
|
|
||||||
using Vertices_map = Unique_hash_map<Vertex_handle, Event*>;
|
using Vertices_map = Unique_hash_map<Vertex_handle, Event*>;
|
||||||
using Compare_xy_2 = typename Gt2::Compare_xy_2;
|
using Compare_xy_2 = typename Gt2::Compare_xy_2;
|
||||||
|
|
||||||
this->m_visitor->before_sweep();
|
|
||||||
// Allocate all of the Subcurve objects as one block.
|
// Allocate all of the Subcurve objects as one block.
|
||||||
this->m_num_of_subCurves = std::distance(curves_begin, curves_end);
|
this->m_num_of_subCurves = std::distance(curves_begin, curves_end);
|
||||||
if (this->m_num_of_subCurves > 0)
|
if (this->m_num_of_subCurves > 0)
|
||||||
|
|
@ -203,13 +202,29 @@ public:
|
||||||
e_right->add_curve_to_left(this->m_subCurves + index);
|
e_right->add_curve_to_left(this->m_subCurves + index);
|
||||||
this->_add_curve_to_right(e_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->_sweep();
|
||||||
this->_complete_sweep();
|
this->_complete_sweep();
|
||||||
this->m_visitor->after_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:
|
private:
|
||||||
|
|
@ -230,7 +245,6 @@ private:
|
||||||
else return (Event::LEFT_END);
|
else return (Event::LEFT_END);
|
||||||
}
|
}
|
||||||
++circ;
|
++circ;
|
||||||
|
|
||||||
} while (circ != first);
|
} while (circ != first);
|
||||||
|
|
||||||
// If we reached here, we should not keep this vertex.
|
// If we reached here, we should not keep this vertex.
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@
|
||||||
// $Id$
|
// $Id$
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
// Ron Wein <wein@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
|
#ifndef CGAL_GSP_AGG_OP_VISITOR_H
|
||||||
#define CGAL_BSO_2_GSP_AGG_OP_VISITOR_H
|
#define CGAL_GSP_AGG_OP_VISITOR_H
|
||||||
|
|
||||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
#include <CGAL/license/Boolean_set_operations_2.h>
|
||||||
|
|
||||||
|
|
@ -31,7 +31,7 @@ class Gps_agg_op_base_visitor :
|
||||||
Helper_,
|
Helper_,
|
||||||
typename Default::Get<Visitor_, Gps_agg_op_base_visitor<Helper_,
|
typename Default::Get<Visitor_, Gps_agg_op_base_visitor<Helper_,
|
||||||
Arrangement_,
|
Arrangement_,
|
||||||
Visitor_> >::type> {
|
Visitor_>>::type> {
|
||||||
public:
|
public:
|
||||||
using Helper = Helper_;
|
using Helper = Helper_;
|
||||||
using Arrangement_2 = Arrangement_;
|
using Arrangement_2 = Arrangement_;
|
||||||
|
|
@ -43,7 +43,6 @@ public:
|
||||||
private:
|
private:
|
||||||
using Gt2 = Geometry_traits_2;
|
using Gt2 = Geometry_traits_2;
|
||||||
using Arr = Arrangement_2;
|
using Arr = Arrangement_2;
|
||||||
|
|
||||||
using Self = Gps_agg_op_base_visitor<Helper, Arr, Visitor_>;
|
using Self = Gps_agg_op_base_visitor<Helper, Arr, Visitor_>;
|
||||||
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
using Visitor = typename Default::Get<Visitor_, Self>::type;
|
||||||
using Base = Arr_construction_ss_visitor<Helper, Visitor>;
|
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 :
|
class Gps_agg_op_visitor :
|
||||||
public Gps_agg_op_base_visitor<
|
public Gps_agg_op_base_visitor<
|
||||||
Helper_, Arrangement_,
|
Helper_, Arrangement_,
|
||||||
Gps_agg_op_visitor<Helper_, Arrangement_, Visitor_>> {
|
typename Default::Get<Visitor_,
|
||||||
|
Gps_agg_op_visitor<Helper_, Arrangement_, Visitor_>>::type> {
|
||||||
public:
|
public:
|
||||||
using Helper = Helper_;
|
using Helper = Helper_;
|
||||||
using Arrangement_2 = Arrangement_;
|
using Arrangement_2 = Arrangement_;
|
||||||
|
|
@ -145,6 +145,7 @@ private:
|
||||||
using Base = Gps_agg_op_base_visitor<Helper, Arr, Visitor>;
|
using Base = Gps_agg_op_base_visitor<Helper, Arr, Visitor>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Edges_hash = typename Base::Edges_hash;
|
||||||
using Halfedge_handle = typename Base::Halfedge_handle;
|
using Halfedge_handle = typename Base::Halfedge_handle;
|
||||||
using Vertex_handle = typename Base::Vertex_handle;
|
using Vertex_handle = typename Base::Vertex_handle;
|
||||||
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
using X_monotone_curve_2 = typename Gt2::X_monotone_curve_2;
|
||||||
|
|
@ -156,7 +157,7 @@ protected:
|
||||||
// ascending order.
|
// ascending order.
|
||||||
|
|
||||||
public:
|
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) :
|
std::vector<Vertex_handle>* vertices_vec) :
|
||||||
Base(arr, hash),
|
Base(arr, hash),
|
||||||
m_event_count(0),
|
m_event_count(0),
|
||||||
|
|
@ -210,7 +211,7 @@ public:
|
||||||
|
|
||||||
CGAL_assertion((Arr_halfedge_direction)res_he->direction() ==
|
CGAL_assertion((Arr_halfedge_direction)res_he->direction() ==
|
||||||
ARR_LEFT_TO_RIGHT);
|
ARR_LEFT_TO_RIGHT);
|
||||||
_insert_vertex (curr_event, res_he->target());
|
_insert_vertex(curr_event, res_he->target());
|
||||||
return res_he;
|
return res_he;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ protected:
|
||||||
std::size_t m_num_of_polygons; // number of polygons
|
std::size_t m_num_of_polygons; // number of polygons
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Gps_bfs_base_visitor(Edges_hash* edges_hash,
|
Gps_bfs_base_visitor(Edges_hash* edges_hash,
|
||||||
Faces_hash* faces_hash,
|
Faces_hash* faces_hash,
|
||||||
std::size_t n_pgn):
|
std::size_t n_pgn):
|
||||||
|
|
@ -79,12 +78,12 @@ public:
|
||||||
protected:
|
protected:
|
||||||
// compute the inside count of a face
|
// compute the inside count of a face
|
||||||
std::size_t compute_ic(Face_iterator f1,
|
std::size_t compute_ic(Face_iterator f1,
|
||||||
Face_iterator f2,
|
Face_iterator f2,
|
||||||
Halfedge_iterator he) {
|
Halfedge_iterator he) {
|
||||||
CGAL_assertion(m_edges_hash->is_defined(he) &&
|
CGAL_assertion(m_edges_hash->is_defined(he) &&
|
||||||
m_edges_hash->is_defined(he->twin()) &&
|
m_edges_hash->is_defined(he->twin()) &&
|
||||||
m_faces_hash->is_defined(f1) &&
|
m_faces_hash->is_defined(f1) &&
|
||||||
!m_faces_hash->is_defined(f2));
|
! m_faces_hash->is_defined(f2));
|
||||||
std::size_t ic_f2 =
|
std::size_t ic_f2 =
|
||||||
(*m_faces_hash)[f1] - (*m_edges_hash)[he] + (*m_edges_hash)[he->twin()];
|
(*m_faces_hash)[f1] - (*m_edges_hash)[he] + (*m_edges_hash)[he->twin()];
|
||||||
(*m_faces_hash)[f2] = ic_f2;
|
(*m_faces_hash)[f2] = ic_f2;
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,9 @@
|
||||||
// $Id$
|
// $Id$
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
// 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>
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Efi Fogel <efifogel@gmail.com>
|
||||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
|
||||||
|
|
||||||
#ifndef CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
#ifndef CGAL_GPS_BFS_INTERSECTION_VISITOR_H
|
||||||
#define 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
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
// $Id$
|
// $Id$
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
//
|
//
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
|
// Efi Fogel <efifogel@gmail.com>
|
||||||
|
|
||||||
#ifndef CGAL_GPS_MERGE_H
|
#ifndef CGAL_GPS_MERGE_H
|
||||||
#define CGAL_GPS_MERGE_H
|
#define CGAL_GPS_MERGE_H
|
||||||
|
|
@ -15,6 +16,8 @@
|
||||||
#include <CGAL/license/Boolean_set_operations_2.h>
|
#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.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_join_visitor.h>
|
||||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_xor_visitor.h>
|
#include <CGAL/Boolean_set_operations_2/Gps_bfs_xor_visitor.h>
|
||||||
#include <CGAL/Boolean_set_operations_2/Gps_bfs_intersection_visitor.h>
|
#include <CGAL/Boolean_set_operations_2/Gps_bfs_intersection_visitor.h>
|
||||||
|
|
@ -23,16 +26,16 @@
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
/*! \file Gps_merge.h
|
/*! \file Gps_merge.h
|
||||||
* \brief This file contains classes that are responsible for merging
|
*
|
||||||
* two sets of polygons in the divide-and-conquer algorithm.
|
* This file contains classes that are responsible for merging two sets of
|
||||||
* The file contains 3 mergers: Join_merge, Intersection_merge and
|
* polygons in the divide-and-conquer algorithm. The file contains 3 mergers:
|
||||||
* Xor_merge. Join_merge is used when we want to merge the two sets,
|
* Join_merge, Intersection_merge and Xor_merge. Join_merge is used when we want
|
||||||
* Intersection_merge is used for intersection, and Xor_merge is used
|
* to merge the two sets, Intersection_merge is used for intersection, and
|
||||||
* for symmetric difference.
|
* Xor_merge is used for symmetric difference.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! Base_merge
|
/*! Base_merge
|
||||||
/*! Base_merge is the base class for all merger classes.
|
* Base_merge is the base class for all merger classes.
|
||||||
* All merges used BFS algorithm with a different visitor when discovering
|
* All merges used BFS algorithm with a different visitor when discovering
|
||||||
* a new face.
|
* a new face.
|
||||||
*/
|
*/
|
||||||
|
|
@ -44,17 +47,15 @@ class Base_merge {
|
||||||
using Arr_entry = std::pair<Arrangement_2*, std::vector<Vertex_handle>*>;
|
using Arr_entry = std::pair<Arrangement_2*, std::vector<Vertex_handle>*>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void operator()(std::size_t i, std::size_t j, std::size_t jump,
|
void operator()(std::size_t i, std::size_t j, std::size_t jump, std::vector<Arr_entry>& arr_vec) {
|
||||||
std::vector<Arr_entry>& arr_vec) {
|
|
||||||
if (i == j) return;
|
if (i == j) return;
|
||||||
|
|
||||||
const typename Arrangement_2::Geometry_traits_2* tr =
|
const auto* tr = arr_vec[i].first->geometry_traits();
|
||||||
arr_vec[i].first->geometry_traits();
|
|
||||||
Arrangement_2* res = new Arrangement_2(tr);
|
Arrangement_2* res = new Arrangement_2(tr);
|
||||||
std::vector<Vertex_handle>* verts = new std::vector<Vertex_handle>;
|
std::vector<Vertex_handle>* verts = new std::vector<Vertex_handle>;
|
||||||
|
|
||||||
Gps_agg_op<Arrangement_2, Visitor>
|
using Agg_op = Gps_agg_op<Arrangement_2, Visitor, Gps_agg_op_visitor>;
|
||||||
agg_op(*res, *verts, *(res->traits_adaptor()));
|
Agg_op agg_op(*res, *verts, *(res->traits_adaptor()));
|
||||||
agg_op.sweep_arrangements(i, j, jump, arr_vec);
|
agg_op.sweep_arrangements(i, j, jump, arr_vec);
|
||||||
|
|
||||||
for (std::size_t count = i; count <= j; count += jump) {
|
for (std::size_t count = i; count <= j; count += jump) {
|
||||||
|
|
@ -67,29 +68,69 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Join_merge
|
/*! Base_intercepted_merge
|
||||||
/*! Join_merge is used to join two sets of polygons together in the D&C
|
* 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.
|
* algorithm. It is a base merge with a visitor that joins faces.
|
||||||
*/
|
*/
|
||||||
template <typename Arrangement_>
|
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
|
||||||
/*! Intersection_merge is used to merge two sets of polygons creating their
|
* Intersection_merge is used to merge two sets of polygons creating their
|
||||||
* intersection.
|
* intersection.
|
||||||
*/
|
*/
|
||||||
template <typename Arrangement_>
|
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
|
/*! Do_intersect_merge
|
||||||
/*! Xor_merge is used to merge two sets of polygons creating their
|
* 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.
|
* symmetric difference.
|
||||||
*/
|
*/
|
||||||
template <typename Arrangement_>
|
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
|
} //namespace CGAL
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
// Ophir Setter <ophir.setter@cs.tau.ac.il>
|
||||||
// Guy Zucker <guyzucke@post.tau.ac.il>
|
// Guy Zucker <guyzucke@post.tau.ac.il>
|
||||||
|
// Efi Fogel <efifogel@gmail.com>
|
||||||
|
|
||||||
#ifndef CGAL_GPS_ON_SURFACE_BASE_2_H
|
#ifndef CGAL_GPS_ON_SURFACE_BASE_2_H
|
||||||
#define CGAL_GPS_ON_SURFACE_BASE_2_H
|
#define CGAL_GPS_ON_SURFACE_BASE_2_H
|
||||||
|
|
@ -388,18 +388,19 @@ public:
|
||||||
|
|
||||||
const Traits_2& traits() const { return *m_traits; }
|
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
|
||||||
// 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
|
||||||
// contained in the polygon set (there can be several faces in an empty
|
// arrangement, dependent on the topology traits.
|
||||||
// arrangement, dependent on the topology traits.
|
// The point is that if the arrangement is "empty" (meaning that no curve
|
||||||
// The point is that if the arrangement is "empty" (meaning that no curve
|
// or point were inserted and that it is in its original state) then
|
||||||
// or point were inserted and that it is in its original state) then
|
// all the faces (created by the topology traits) should have the same
|
||||||
// all the faces (created by the topology traits) should have the same
|
// result for contained() --- from Boolean operations point of view there
|
||||||
// result for contained() --- from Boolean operations point of view there
|
// can not be an empty arrangement which has several faces with different
|
||||||
// can not be an empty arrangement which has several faces with different
|
// attributes.
|
||||||
// attributes.
|
bool is_empty() const { this->_is_empty(m_arr); }
|
||||||
return (m_arr->is_empty() && !m_arr->faces_begin()->contained());
|
|
||||||
}
|
bool _is_empty(Aos_2* arr) const
|
||||||
|
{ return (arr->is_empty() && ! arr->faces_begin()->contained()); }
|
||||||
|
|
||||||
bool is_plane() const {
|
bool is_plane() const {
|
||||||
// Same comment as in "is_empty" above, just with adjustments.
|
// Same comment as in "is_empty" above, just with adjustments.
|
||||||
|
|
@ -493,8 +494,33 @@ public:
|
||||||
template <typename InputIterator>
|
template <typename InputIterator>
|
||||||
bool do_intersect(InputIterator begin, InputIterator end, std::size_t k = 5) {
|
bool do_intersect(InputIterator begin, InputIterator end, std::size_t k = 5) {
|
||||||
Self other(*this);
|
Self other(*this);
|
||||||
other.intersection(begin, end, k);
|
return other._do_intersect(begin, end, k);
|
||||||
return (other.is_empty());
|
}
|
||||||
|
|
||||||
|
// 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>
|
template <typename InputIterator1, typename InputIterator2>
|
||||||
|
|
@ -502,8 +528,40 @@ public:
|
||||||
InputIterator2 begin2, InputIterator2 end2,
|
InputIterator2 begin2, InputIterator2 end2,
|
||||||
std::size_t k = 5) {
|
std::size_t k = 5) {
|
||||||
Self other(*this);
|
Self other(*this);
|
||||||
other.intersection(begin1, end1, begin2, end2, k);
|
return other._do_intersect(begin1, end1, begin2, end2, k);
|
||||||
return (other.is_empty());
|
}
|
||||||
|
|
||||||
|
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
|
// joins a range of polygons
|
||||||
|
|
@ -533,7 +591,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Join_merge<Aos_2> join_merge;
|
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);
|
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, join_merge);
|
||||||
|
|
||||||
//the result arrangement is at index 0
|
//the result arrangement is at index 0
|
||||||
|
|
@ -556,7 +613,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Join_merge<Aos_2> join_merge;
|
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);
|
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, join_merge);
|
||||||
|
|
||||||
// the result arrangement is at index 0
|
// the result arrangement is at index 0
|
||||||
|
|
@ -585,7 +641,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Join_merge<Aos_2> join_merge;
|
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);
|
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, join_merge);
|
||||||
|
|
||||||
// the result arrangement is at index 0
|
// the result arrangement is at index 0
|
||||||
|
|
@ -620,7 +675,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Intersection_merge<Aos_2> intersection_merge;
|
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);
|
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, intersection_merge);
|
||||||
|
|
||||||
// the result arrangement is at index 0
|
// the result arrangement is at index 0
|
||||||
|
|
@ -636,14 +690,13 @@ public:
|
||||||
arr_vec[0].first = this->m_arr;
|
arr_vec[0].first = this->m_arr;
|
||||||
std::size_t i = 1;
|
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);
|
ValidationPolicy::is_valid((*itr), *m_traits);
|
||||||
arr_vec[i].first = new Aos_2(m_traits);
|
arr_vec[i].first = new Aos_2(m_traits);
|
||||||
_insert(*itr, *(arr_vec[i].first));
|
_insert(*itr, *(arr_vec[i].first));
|
||||||
}
|
}
|
||||||
|
|
||||||
Intersection_merge<Aos_2> intersection_merge;
|
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);
|
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, intersection_merge);
|
||||||
|
|
||||||
// the result arrangement is at index 0
|
// the result arrangement is at index 0
|
||||||
|
|
@ -659,20 +712,19 @@ public:
|
||||||
arr_vec[0].first = this->m_arr;
|
arr_vec[0].first = this->m_arr;
|
||||||
std::size_t i = 1;
|
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);
|
ValidationPolicy::is_valid(*itr1, *m_traits);
|
||||||
arr_vec[i].first = new Aos_2(m_traits);
|
arr_vec[i].first = new Aos_2(m_traits);
|
||||||
_insert(*itr1, *(arr_vec[i].first));
|
_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);
|
ValidationPolicy::is_valid(*itr2,*m_traits);
|
||||||
arr_vec[i].first = new Aos_2(m_traits);
|
arr_vec[i].first = new Aos_2(m_traits);
|
||||||
_insert(*itr2, *(arr_vec[i].first));
|
_insert(*itr2, *(arr_vec[i].first));
|
||||||
}
|
}
|
||||||
|
|
||||||
Intersection_merge<Aos_2> intersection_merge;
|
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);
|
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, intersection_merge);
|
||||||
|
|
||||||
// the result arrangement is at index 0
|
// the result arrangement is at index 0
|
||||||
|
|
@ -708,7 +760,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Xor_merge<Aos_2> xor_merge;
|
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);
|
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, xor_merge);
|
||||||
|
|
||||||
// the result arrangement is at index 0
|
// the result arrangement is at index 0
|
||||||
|
|
@ -731,7 +782,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Xor_merge<Aos_2> xor_merge;
|
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);
|
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, xor_merge);
|
||||||
|
|
||||||
// the result arrangement is at index 0
|
// the result arrangement is at index 0
|
||||||
|
|
@ -761,7 +811,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Xor_merge<Aos_2> xor_merge;
|
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);
|
_divide_and_conquer(0, arr_vec.size() - 1, arr_vec, k, xor_merge);
|
||||||
|
|
||||||
// the result arrangement is at index 0
|
// 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());
|
Less_vertex_handle comp(m_traits->compare_xy_2_object());
|
||||||
const std::size_t n = arr_vec.size();
|
for (std::size_t i = lower; i < upper + 1; i++) {
|
||||||
for (std::size_t i = 0; i < n; i++) {
|
|
||||||
// Allocate a vector of handles to all vertices in the current arrangement.
|
// Allocate a vector of handles to all vertices in the current arrangement.
|
||||||
Aos_2* p_arr = arr_vec[i].first;
|
Aos_2* p_arr = arr_vec[i].first;
|
||||||
arr_vec[i].second = new std::vector<Vertex_handle>;
|
arr_vec[i].second = new std::vector<Vertex_handle>;
|
||||||
|
|
@ -1174,11 +1223,16 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Divide & conquer
|
||||||
template <typename Merge>
|
template <typename Merge>
|
||||||
void _divide_and_conquer(std::size_t lower, std::size_t upper,
|
void _divide_and_conquer(std::size_t lower, std::size_t upper,
|
||||||
std::vector<Arr_entry>& arr_vec,
|
std::vector<Arr_entry>& arr_vec,
|
||||||
std::size_t k, Merge merge_func) {
|
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) {
|
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);
|
merge_func(lower, upper, 1, arr_vec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1187,12 +1241,71 @@ protected:
|
||||||
auto curr_lower = lower;
|
auto curr_lower = lower;
|
||||||
|
|
||||||
for (std::size_t i = 0; i < k - 1; ++i, curr_lower += sub_size) {
|
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);
|
_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);
|
_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);
|
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
|
// marks all faces as non-visited
|
||||||
void _reset_faces() const { _reset_faces(m_arr); }
|
void _reset_faces() const { _reset_faces(m_arr); }
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue