Adapt to package style: Indent two spaces, brackets on own lines

Astyle options:

    --style=break
    --indent=spaces=2
    --max-code-length=80
    --attach-namespaces
This commit is contained in:
Sebastian Morr 2014-08-09 08:58:52 +02:00
parent 6c354e34da
commit 1bc8f28969
4 changed files with 580 additions and 468 deletions

View File

@ -9,7 +9,8 @@ namespace CGAL {
// Tests whether two polygons P and Q overlap for different translations of Q. // Tests whether two polygons P and Q overlap for different translations of Q.
template <class Kernel_, class Container_> template <class Kernel_, class Container_>
class AABB_collision_detector_2 { class AABB_collision_detector_2
{
public: public:
@ -17,24 +18,31 @@ public:
typedef typename Kernel_::Vector_2 Vector_2; typedef typename Kernel_::Vector_2 Vector_2;
typedef typename CGAL::Polygon_2<Kernel_> Polygon_2; typedef typename CGAL::Polygon_2<Kernel_> Polygon_2;
typedef typename Polygon_2::Edge_const_iterator Edge_iterator; typedef typename Polygon_2::Edge_const_iterator Edge_iterator;
typedef AABB_segment_2_primitive<Kernel_, Edge_iterator, Polygon_2> Tree_segment_2; typedef AABB_segment_2_primitive<Kernel_, Edge_iterator, Polygon_2>
Tree_segment_2;
typedef AABB_traits_2<Kernel_, Tree_segment_2> Tree_traits; typedef AABB_traits_2<Kernel_, Tree_segment_2> Tree_traits;
typedef AABB_tree<Tree_traits> Tree_2; typedef AABB_tree<Tree_traits> Tree_2;
public: public:
AABB_collision_detector_2(const Polygon_2 &p, const Polygon_2 &q) AABB_collision_detector_2(const Polygon_2 &p, const Polygon_2 &q)
: m_stationary_tree((p.edges_begin()), (p.edges_end())), m_translating_tree((q.edges_begin()), (q.edges_end())), m_p(q), m_q(p) { : m_stationary_tree((p.edges_begin()), (p.edges_end())),
m_translating_tree((q.edges_begin()), (q.edges_end())), m_p(q), m_q(p)
{
} }
// Returns true iff the polygons' boundaries intersect or one polygon is completely inside of the other one. Q is translated by t. // Returns true iff the polygons' boundaries intersect or one polygon is completely inside of the other one. Q is translated by t.
bool check_collision(const Point_2 &t) { bool check_collision(const Point_2 &t)
if (m_stationary_tree.do_intersect(m_translating_tree, t)) { {
if (m_stationary_tree.do_intersect(m_translating_tree, t))
{
return true; return true;
} }
Polygon_2 translated_p = transform(typename Kernel_::Aff_transformation_2(Translation(), Vector_2(ORIGIN, t)), m_p); Polygon_2 translated_p = transform(typename Kernel_::Aff_transformation_2(
return (translated_p.has_on_bounded_side(*(m_q.vertices_begin())) || m_q.has_on_bounded_side(*(translated_p.vertices_begin()))); Translation(), Vector_2(ORIGIN, t)), m_p);
return (translated_p.has_on_bounded_side(*(m_q.vertices_begin()))
|| m_q.has_on_bounded_side(*(translated_p.vertices_begin())));
} }
private: private:

View File

@ -5,7 +5,8 @@ namespace CGAL {
// Wraps around a Segment_2 and provides its iterator as Id // Wraps around a Segment_2 and provides its iterator as Id
template <class GeomTraits, class Iterator_, class ContainerType> template <class GeomTraits, class Iterator_, class ContainerType>
class AABB_segment_2_primitive { class AABB_segment_2_primitive
{
public: public:
@ -16,23 +17,28 @@ public:
AABB_segment_2_primitive() {} AABB_segment_2_primitive() {}
AABB_segment_2_primitive(Id it) : m_it(it) { AABB_segment_2_primitive(Id it) : m_it(it)
{
} }
AABB_segment_2_primitive(const AABB_segment_2_primitive &primitive) { AABB_segment_2_primitive(const AABB_segment_2_primitive &primitive)
{
m_it = primitive.id(); m_it = primitive.id();
} }
const Id &id() const { const Id &id() const
{
return m_it; return m_it;
} }
const Datum datum() const { const Datum datum() const
{
return *m_it; return *m_it;
} }
// Return a point on the primitive // Return a point on the primitive
Point reference_point() const { Point reference_point() const
{
return datum().source(); return datum().source();
} }

View File

@ -4,7 +4,8 @@
namespace CGAL { namespace CGAL {
template<typename GeomTraits, typename AABB_primitive_> template<typename GeomTraits, typename AABB_primitive_>
class AABB_traits_2 { class AABB_traits_2
{
public: public:
@ -30,63 +31,80 @@ public:
typedef typename GeomTraits::Construct_min_vertex_2 Construct_min_vertex_3; typedef typename GeomTraits::Construct_min_vertex_2 Construct_min_vertex_3;
typedef typename GeomTraits::Construct_max_vertex_2 Construct_max_vertex_3; typedef typename GeomTraits::Construct_max_vertex_2 Construct_max_vertex_3;
typedef typename GeomTraits::Compute_squared_radius_2 Compute_squared_radius_3; typedef typename GeomTraits::Compute_squared_radius_2 Compute_squared_radius_3;
typedef typename GeomTraits::Cartesian_const_iterator_2 Cartesian_const_iterator_3; typedef typename GeomTraits::Cartesian_const_iterator_2
typedef typename GeomTraits::Construct_cartesian_const_iterator_2 Construct_cartesian_const_iterator_3; Cartesian_const_iterator_3;
typedef typename GeomTraits::Construct_cartesian_const_iterator_2
Construct_cartesian_const_iterator_3;
AABB_traits_2(const Point &translation_point): m_translation_point(translation_point) { AABB_traits_2(const Point &translation_point): m_translation_point(
translation_point)
{
m_interval_x = Interval_nt<true>(to_interval(translation_point.x())); m_interval_x = Interval_nt<true>(to_interval(translation_point.x()));
m_interval_y = Interval_nt<true>(to_interval(translation_point.y())); m_interval_y = Interval_nt<true>(to_interval(translation_point.y()));
}; };
AABB_traits_2() { AABB_traits_2()
{
m_translation_point = Point(0, 0); m_translation_point = Point(0, 0);
m_interval_x = Interval_nt<true>(0); m_interval_x = Interval_nt<true>(0);
m_interval_y = Interval_nt<true>(0); m_interval_y = Interval_nt<true>(0);
}; };
Interval_nt<true> get_interval_x() const { Interval_nt<true> get_interval_x() const
{
return m_interval_x; return m_interval_x;
} }
Interval_nt<true> get_interval_y() const { Interval_nt<true> get_interval_y() const
{
return m_interval_y; return m_interval_y;
} }
Point get_translation_point() const { Point get_translation_point() const
{
return m_translation_point; return m_translation_point;
} }
// Put the n/2 smallest primitives in the front, the n/2 largest primitives // Put the n/2 smallest primitives in the front, the n/2 largest primitives
// in the back. They are compared along the bbox' longest axis. // in the back. They are compared along the bbox' longest axis.
class Sort_primitives { class Sort_primitives
{
public: public:
template<typename PrimitiveIterator> template<typename PrimitiveIterator>
void operator()(PrimitiveIterator first, void operator()(PrimitiveIterator first,
PrimitiveIterator beyond, PrimitiveIterator beyond,
const Bounding_box &bbox) const { const Bounding_box &bbox) const
{
PrimitiveIterator middle = first + (beyond - first) / 2; PrimitiveIterator middle = first + (beyond - first) / 2;
if (bbox.xmax()-bbox.xmin() >= bbox.ymax()-bbox.ymin()) { if (bbox.xmax()-bbox.xmin() >= bbox.ymax()-bbox.ymin())
{
std::nth_element(first, middle, beyond, less_x); // sort along x std::nth_element(first, middle, beyond, less_x); // sort along x
} else { }
else
{
std::nth_element(first, middle, beyond, less_y); // sort along y std::nth_element(first, middle, beyond, less_y); // sort along y
} }
} }
}; };
Sort_primitives sort_primitives_object() const { Sort_primitives sort_primitives_object() const
{
return Sort_primitives(); return Sort_primitives();
} }
// Computes the bounding box of a set of primitives // Computes the bounding box of a set of primitives
class Compute_bbox { class Compute_bbox
{
public: public:
template<typename ConstPrimitiveIterator> template<typename ConstPrimitiveIterator>
Bounding_box operator()(ConstPrimitiveIterator first, Bounding_box operator()(ConstPrimitiveIterator first,
ConstPrimitiveIterator beyond) const { ConstPrimitiveIterator beyond) const
{
Bounding_box bbox = first->datum().bbox(); Bounding_box bbox = first->datum().bbox();
for (++first; first != beyond; ++first) { for (++first; first != beyond; ++first)
{
bbox = bbox + first->datum().bbox(); bbox = bbox + first->datum().bbox();
} }
@ -94,11 +112,13 @@ public:
} }
}; };
Compute_bbox compute_bbox_object() const { Compute_bbox compute_bbox_object() const
{
return Compute_bbox(); return Compute_bbox();
} }
class Do_intersect { class Do_intersect
{
private: private:
@ -108,35 +128,48 @@ public:
Do_intersect(AABB_traits_2 *_traits): m_traits(_traits) {} Do_intersect(AABB_traits_2 *_traits): m_traits(_traits) {}
bool operator()(const Bounding_box &q, const Bounding_box &bbox) const { bool operator()(const Bounding_box &q, const Bounding_box &bbox) const
{
Interval_nt<true> x1 = Interval_nt<true>(q.xmin(), q.xmax()); Interval_nt<true> x1 = Interval_nt<true>(q.xmin(), q.xmax());
Interval_nt<true> y1 = Interval_nt<true>(q.ymin(), q.ymax()); Interval_nt<true> y1 = Interval_nt<true>(q.ymin(), q.ymax());
Interval_nt<true> x2 = Interval_nt<true>(bbox.xmin(), bbox.xmax()) + m_traits->get_interval_x(); Interval_nt<true> x2 = Interval_nt<true>(bbox.xmin(),
Interval_nt<true> y2 = Interval_nt<true>(bbox.ymin(), bbox.ymax()) + m_traits->get_interval_y(); bbox.xmax()) + m_traits->get_interval_x();
Interval_nt<true> y2 = Interval_nt<true>(bbox.ymin(),
bbox.ymax()) + m_traits->get_interval_y();
return x1.do_overlap(x2) && y1.do_overlap(y2); return x1.do_overlap(x2) && y1.do_overlap(y2);
} }
bool operator()(const Primitive &q, const Bounding_box &bbox) const { bool operator()(const Primitive &q, const Bounding_box &bbox) const
Interval_nt<true> x1 = Interval_nt<true>(q.datum().bbox().xmin(), q.datum().bbox().xmax()); {
Interval_nt<true> y1 = Interval_nt<true>(q.datum().bbox().ymin(), q.datum().bbox().ymax()); Interval_nt<true> x1 = Interval_nt<true>(q.datum().bbox().xmin(),
Interval_nt<true> x2 = Interval_nt<true>(bbox.xmin(), bbox.xmax()) + m_traits->get_interval_x(); q.datum().bbox().xmax());
Interval_nt<true> y2 = Interval_nt<true>(bbox.ymin(), bbox.ymax()) + m_traits->get_interval_y(); Interval_nt<true> y1 = Interval_nt<true>(q.datum().bbox().ymin(),
q.datum().bbox().ymax());
Interval_nt<true> x2 = Interval_nt<true>(bbox.xmin(),
bbox.xmax()) + m_traits->get_interval_x();
Interval_nt<true> y2 = Interval_nt<true>(bbox.ymin(),
bbox.ymax()) + m_traits->get_interval_y();
return x1.do_overlap(x2) && y1.do_overlap(y2); return x1.do_overlap(x2) && y1.do_overlap(y2);
} }
bool operator()(const Bounding_box &q, const Primitive &pr) const { bool operator()(const Bounding_box &q, const Primitive &pr) const
Datum tr_pr = pr.datum().transform(typename GeomTraits::Aff_transformation_2(Translation(), {
Datum tr_pr = pr.datum().transform(typename GeomTraits::Aff_transformation_2(
Translation(),
Vector_2(ORIGIN, m_traits->get_translation_point()))); Vector_2(ORIGIN, m_traits->get_translation_point())));
return do_overlap(q, tr_pr.bbox()); return do_overlap(q, tr_pr.bbox());
} }
bool operator()(const Primitive &q, const Primitive &pr) const { bool operator()(const Primitive &q, const Primitive &pr) const
Datum tr_pr = pr.datum().transform(typename GeomTraits::Aff_transformation_2(Translation(), Vector_2(ORIGIN, m_traits->get_translation_point()))); {
Datum tr_pr = pr.datum().transform(typename GeomTraits::Aff_transformation_2(
Translation(), Vector_2(ORIGIN, m_traits->get_translation_point())));
if (!do_overlap(q.datum().bbox(), tr_pr.bbox())) { if (!do_overlap(q.datum().bbox(), tr_pr.bbox()))
{
return false; return false;
} }
@ -144,7 +177,8 @@ public:
} }
}; };
Do_intersect do_intersect_object() { Do_intersect do_intersect_object()
{
return Do_intersect(this); return Do_intersect(this);
} }
@ -155,11 +189,13 @@ private:
Interval_nt<true> m_interval_y; Interval_nt<true> m_interval_y;
// Comparison functions // Comparison functions
static bool less_x(const Primitive &pr1, const Primitive &pr2) { static bool less_x(const Primitive &pr1, const Primitive &pr2)
{
return pr1.reference_point().x() < pr2.reference_point().x(); return pr1.reference_point().x() < pr2.reference_point().x();
} }
static bool less_y(const Primitive &pr1, const Primitive &pr2) { static bool less_y(const Primitive &pr1, const Primitive &pr2)
{
return pr1.reference_point().y() < pr2.reference_point().y(); return pr1.reference_point().y() < pr2.reference_point().y();
} }
}; };

View File

@ -16,7 +16,8 @@
namespace CGAL { namespace CGAL {
template <class Kernel_, class Container_> template <class Kernel_, class Container_>
class Minkowski_sum_by_reduced_convolution_2 { class Minkowski_sum_by_reduced_convolution_2
{
private: private:
@ -43,8 +44,10 @@ private:
typedef typename Arrangement_history_2::Halfedge_handle Halfedge_handle; typedef typename Arrangement_history_2::Halfedge_handle Halfedge_handle;
typedef typename Arrangement_history_2::Face_iterator Face_iterator; typedef typename Arrangement_history_2::Face_iterator Face_iterator;
typedef typename Arrangement_history_2::Face_handle Face_handle; typedef typename Arrangement_history_2::Face_handle Face_handle;
typedef typename Arrangement_history_2::Ccb_halfedge_circulator Ccb_halfedge_circulator; typedef typename Arrangement_history_2::Ccb_halfedge_circulator
typedef typename Arrangement_history_2::Originating_curve_iterator Originating_curve_iterator; Ccb_halfedge_circulator;
typedef typename Arrangement_history_2::Originating_curve_iterator
Originating_curve_iterator;
// Function object types: // Function object types:
typename Kernel::Construct_translated_point_2 f_add; typename Kernel::Construct_translated_point_2 f_add;
@ -56,7 +59,8 @@ private:
public: public:
Minkowski_sum_by_reduced_convolution_2() { Minkowski_sum_by_reduced_convolution_2()
{
// Obtain kernel functors // Obtain kernel functors
Kernel ker; Kernel ker;
f_add = ker.construct_translated_point_2_object(); f_add = ker.construct_translated_point_2_object();
@ -69,7 +73,8 @@ public:
template <class OutputIterator> template <class OutputIterator>
void operator()(const Polygon_2 &pgn1, const Polygon_2 &pgn2, void operator()(const Polygon_2 &pgn1, const Polygon_2 &pgn2,
Polygon_2 &outer_boundary, OutputIterator holes) const { Polygon_2 &outer_boundary, OutputIterator holes) const
{
Timer timer; // TODO: remove when optimization is done Timer timer; // TODO: remove when optimization is done
timer.start(); timer.start();
@ -85,8 +90,10 @@ public:
timer.start(); timer.start();
// Initialize collision detector. It operates on pgn2 and on the inversed pgn1: // Initialize collision detector. It operates on pgn2 and on the inversed pgn1:
const Polygon_2 inversed_pgn1 = transform(Aff_transformation_2<Kernel>(SCALING, -1), pgn1); const Polygon_2 inversed_pgn1 = transform(Aff_transformation_2<Kernel>(SCALING,
AABB_collision_detector_2<Kernel, Container> collision_detector(pgn2, inversed_pgn1); -1), pgn1);
AABB_collision_detector_2<Kernel, Container> collision_detector(pgn2,
inversed_pgn1);
timer.stop(); timer.stop();
std::cout << timer.time() << " s: AABB init" << std::endl; std::cout << timer.time() << " s: AABB init" << std::endl;
@ -120,7 +127,8 @@ public:
timer.start(); timer.start();
// Check for each face whether it is a hole in the M-sum. If it is, add it to 'holes'. // Check for each face whether it is a hole in the M-sum. If it is, add it to 'holes'.
for (Face_iterator face = arr.faces_begin(); face != arr.faces_end(); ++face) { for (Face_iterator face = arr.faces_begin(); face != arr.faces_end(); ++face)
{
handle_face(arr, face, holes, collision_detector); handle_face(arr, face, holes, collision_detector);
} }
@ -135,7 +143,9 @@ private:
// vertex is reached, then do not explore further. This is a BFS-like // vertex is reached, then do not explore further. This is a BFS-like
// iteration beginning from each vertex in the first column of the fiber // iteration beginning from each vertex in the first column of the fiber
// grid. // grid.
void build_reduced_convolution(const Polygon_2 &pgn1, const Polygon_2 &pgn2, Segment_list &reduced_convolution) const { void build_reduced_convolution(const Polygon_2 &pgn1, const Polygon_2 &pgn2,
Segment_list &reduced_convolution) const
{
unsigned int n1 = pgn1.size(); unsigned int n1 = pgn1.size();
unsigned int n2 = pgn2.size(); unsigned int n2 = pgn2.size();
@ -148,11 +158,13 @@ private:
// Init the queue with vertices from the first column // Init the queue with vertices from the first column
std::queue<State> state_queue; std::queue<State> state_queue;
for (int i = n1-1; i >= 0; --i) { for (int i = n1-1; i >= 0; --i)
{
state_queue.push(State(i, 0)); state_queue.push(State(i, 0));
} }
while (state_queue.size() > 0) { while (state_queue.size() > 0)
{
State curr_state = state_queue.front(); State curr_state = state_queue.front();
state_queue.pop(); state_queue.pop();
@ -160,7 +172,8 @@ private:
int i2 = curr_state.second; int i2 = curr_state.second;
// If this state was already visited, skip it // If this state was already visited, skip it
if (visited_states.count(curr_state) > 0) { if (visited_states.count(curr_state) > 0)
{
continue; continue;
} }
visited_states.insert(curr_state); visited_states.insert(curr_state);
@ -172,12 +185,16 @@ private:
// Try two transitions: From (i,j) to (i+1,j) and to (i,j+1). Add // Try two transitions: From (i,j) to (i+1,j) and to (i,j+1). Add
// the respective segments, if they are in the reduced convolution. // the respective segments, if they are in the reduced convolution.
for(int step_in_pgn1 = 0; step_in_pgn1 <= 1; step_in_pgn1++) { for(int step_in_pgn1 = 0; step_in_pgn1 <= 1; step_in_pgn1++)
{
int new_i1, new_i2; int new_i1, new_i2;
if (step_in_pgn1) { if (step_in_pgn1)
{
new_i1 = next_i1; new_i1 = next_i1;
new_i2 = i2; new_i2 = i2;
} else { }
else
{
new_i1 = i1; new_i1 = i1;
new_i2 = next_i2; new_i2 = next_i2;
} }
@ -186,27 +203,37 @@ private:
// the other polygon's vertex' ingoing and outgoing directions, // the other polygon's vertex' ingoing and outgoing directions,
// the segment belongs to the full convolution. // the segment belongs to the full convolution.
bool belongs_to_convolution; bool belongs_to_convolution;
if (step_in_pgn1) { if (step_in_pgn1)
belongs_to_convolution = f_ccw_in_between(p1_dirs[i1], p2_dirs[prev_i2], p2_dirs[i2]) || {
belongs_to_convolution = f_ccw_in_between(p1_dirs[i1], p2_dirs[prev_i2],
p2_dirs[i2]) ||
p1_dirs[i1] == p2_dirs[i2]; p1_dirs[i1] == p2_dirs[i2];
} else { }
belongs_to_convolution = f_ccw_in_between(p2_dirs[i2], p1_dirs[prev_i1], p1_dirs[i1]) || else
{
belongs_to_convolution = f_ccw_in_between(p2_dirs[i2], p1_dirs[prev_i1],
p1_dirs[i1]) ||
p2_dirs[i2] == p1_dirs[prev_i1]; p2_dirs[i2] == p1_dirs[prev_i1];
} }
if (belongs_to_convolution) { if (belongs_to_convolution)
{
state_queue.push(State(new_i1, new_i2)); state_queue.push(State(new_i1, new_i2));
// Only edges added to convex vertices can be on the M-sum's boundary. // Only edges added to convex vertices can be on the M-sum's boundary.
// This filter only leaves the *reduced* convolution. // This filter only leaves the *reduced* convolution.
bool convex; bool convex;
if (step_in_pgn1) { if (step_in_pgn1)
{
convex = is_convex(pgn2[prev_i2], pgn2[i2], pgn2[next_i2]); convex = is_convex(pgn2[prev_i2], pgn2[i2], pgn2[next_i2]);
} else { }
else
{
convex = is_convex(pgn1[prev_i1], pgn1[i1], pgn1[next_i1]); convex = is_convex(pgn1[prev_i1], pgn1[i1], pgn1[next_i1]);
} }
if (convex) { if (convex)
{
Point_2 start_point = get_point(i1, i2, pgn1, pgn2); Point_2 start_point = get_point(i1, i2, pgn1, pgn2);
Point_2 end_point = get_point(new_i1, new_i2, pgn1, pgn2); Point_2 end_point = get_point(new_i1, new_i2, pgn1, pgn2);
reduced_convolution.push_back(Segment_2(start_point, end_point)); reduced_convolution.push_back(Segment_2(start_point, end_point));
@ -217,11 +244,13 @@ private:
} }
// Returns a sorted list of the polygon's edges // Returns a sorted list of the polygon's edges
std::vector<Direction_2> directions_of_polygon(const Polygon_2 &p) const { std::vector<Direction_2> directions_of_polygon(const Polygon_2 &p) const
{
std::vector<Direction_2> directions; std::vector<Direction_2> directions;
unsigned int n = p.size(); unsigned int n = p.size();
for (int i = 0; i < n-1; ++i) { for (int i = 0; i < n-1; ++i)
{
directions.push_back(f_direction(f_vector(p[i], p[i+1]))); directions.push_back(f_direction(f_vector(p[i], p[i+1])));
} }
directions.push_back(f_direction(f_vector(p[n-1], p[0]))); directions.push_back(f_direction(f_vector(p[n-1], p[0])));
@ -229,32 +258,44 @@ private:
return directions; return directions;
} }
bool is_convex(const Point_2 &prev, const Point_2 &curr, const Point_2 &next) const { bool is_convex(const Point_2 &prev, const Point_2 &curr,
const Point_2 &next) const
{
return f_orientation(prev, curr, next) == LEFT_TURN; return f_orientation(prev, curr, next) == LEFT_TURN;
} }
// Returns the point corresponding to a state (i,j). // Returns the point corresponding to a state (i,j).
Point_2 get_point(int i1, int i2, const Polygon_2 &pgn1, const Polygon_2 &pgn2) const { Point_2 get_point(int i1, int i2, const Polygon_2 &pgn1,
const Polygon_2 &pgn2) const
{
return f_add(pgn1[i1], Vector_2(Point_2(ORIGIN), pgn2[i2])); return f_add(pgn1[i1], Vector_2(Point_2(ORIGIN), pgn2[i2]));
} }
// Put the outer loop of the arrangement in 'outer_boundary' // Put the outer loop of the arrangement in 'outer_boundary'
void get_outer_loop(Arrangement_history_2 &arr, Polygon_2 &outer_boundary) const { void get_outer_loop(Arrangement_history_2 &arr,
Polygon_2 &outer_boundary) const
{
Ccb_halfedge_circulator circ_start = *(arr.unbounded_face()->holes_begin()); Ccb_halfedge_circulator circ_start = *(arr.unbounded_face()->holes_begin());
Ccb_halfedge_circulator circ = circ_start; Ccb_halfedge_circulator circ = circ_start;
do { do
{
outer_boundary.push_back(circ->source()->point()); outer_boundary.push_back(circ->source()->point());
} while (--circ != circ_start); }
while (--circ != circ_start);
} }
// Check whether the face is on the M-sum's border. Add it to 'holes' if it is. // Check whether the face is on the M-sum's border. Add it to 'holes' if it is.
template <class OutputIterator> template <class OutputIterator>
void handle_face(const Arrangement_history_2 &arr, const Face_handle face, OutputIterator holes, AABB_collision_detector_2<Kernel, Container> &collision_detector) const { void handle_face(const Arrangement_history_2 &arr, const Face_handle face,
OutputIterator holes, AABB_collision_detector_2<Kernel, Container>
&collision_detector) const
{
// If the face contains holes, it can't be on the Minkowski sum's border // If the face contains holes, it can't be on the Minkowski sum's border
if (face->holes_begin() != face->holes_end()) { if (face->holes_begin() != face->holes_end())
{
return; return;
} }
@ -262,15 +303,19 @@ private:
Ccb_halfedge_circulator circ = start; Ccb_halfedge_circulator circ = start;
// The face needs to be orientable // The face needs to be orientable
do { do
if (!do_original_edges_have_same_direction(arr, circ)) { {
if (!do_original_edges_have_same_direction(arr, circ))
{
return; return;
} }
} while (++circ != start); }
while (++circ != start);
// When the reversed polygon 1, translated by a point inside of this face, collides with polygon 2, this cannot be a hole // When the reversed polygon 1, translated by a point inside of this face, collides with polygon 2, this cannot be a hole
Point_2 inner_point = get_point_in_face(face); Point_2 inner_point = get_point_in_face(face);
if (collision_detector.check_collision(inner_point)) { if (collision_detector.check_collision(inner_point))
{
return; return;
} }
@ -278,20 +323,28 @@ private:
Polygon_2 pgn_hole; Polygon_2 pgn_hole;
circ = start; circ = start;
do { do
{
pgn_hole.push_back(circ->source()->point()); pgn_hole.push_back(circ->source()->point());
} while (--circ != start); }
while (--circ != start);
*holes = pgn_hole; *holes = pgn_hole;
++holes; ++holes;
} }
// Check whether the convolution's original edge(s) had the same direction as the arrangement's half edge // Check whether the convolution's original edge(s) had the same direction as the arrangement's half edge
bool do_original_edges_have_same_direction(const Arrangement_history_2 &arr, const Halfedge_handle he) const { bool do_original_edges_have_same_direction(const Arrangement_history_2 &arr,
const Halfedge_handle he) const
{
Originating_curve_iterator segment_itr; Originating_curve_iterator segment_itr;
for (segment_itr = arr.originating_curves_begin(he); segment_itr != arr.originating_curves_end(he); ++segment_itr) { for (segment_itr = arr.originating_curves_begin(he);
if (f_compare_xy(segment_itr->source(), segment_itr->target()) == (Comparison_result)he->direction()) { segment_itr != arr.originating_curves_end(he); ++segment_itr)
{
if (f_compare_xy(segment_itr->source(),
segment_itr->target()) == (Comparison_result)he->direction())
{
return false; return false;
} }
} }
@ -300,7 +353,8 @@ private:
} }
// Return a point in the face's interior by finding a diagonal // Return a point in the face's interior by finding a diagonal
Point_2 get_point_in_face(const Face_handle face) const { Point_2 get_point_in_face(const Face_handle face) const
{
Ccb_halfedge_circulator current_edge = face->outer_ccb(); Ccb_halfedge_circulator current_edge = face->outer_ccb();
Ccb_halfedge_circulator next_edge = current_edge; Ccb_halfedge_circulator next_edge = current_edge;
next_edge++; next_edge++;
@ -308,25 +362,30 @@ private:
Point_2 a, v, b; Point_2 a, v, b;
// Move over the face's vertices until a convex corner is encountered: // Move over the face's vertices until a convex corner is encountered:
do { do
{
a = current_edge->source()->point(); a = current_edge->source()->point();
v = current_edge->target()->point(); v = current_edge->target()->point();
b = next_edge->target()->point(); b = next_edge->target()->point();
current_edge++; current_edge++;
next_edge++; next_edge++;
} while (!is_convex(a, v, b)); }
while (!is_convex(a, v, b));
Triangle_2 ear(a, v, b); Triangle_2 ear(a, v, b);
FT min_distance = -1; FT min_distance = -1;
Point_2 min_q; Point_2 min_q;
// Of the remaining vertices, find the one inside of the "ear" with minimal distance to v: // Of the remaining vertices, find the one inside of the "ear" with minimal distance to v:
while (++next_edge != current_edge) { while (++next_edge != current_edge)
{
Point_2 q = next_edge->target()->point(); Point_2 q = next_edge->target()->point();
if (ear.has_on_bounded_side(q)) { if (ear.has_on_bounded_side(q))
{
FT distance = squared_distance(q, v); FT distance = squared_distance(q, v);
if (min_distance == -1 || distance < min_distance) { if (min_distance == -1 || distance < min_distance)
{
min_distance = distance; min_distance = distance;
min_q = q; min_q = q;
} }
@ -335,9 +394,12 @@ private:
// If there was no vertex inside of the ear, return it's centroid. // If there was no vertex inside of the ear, return it's centroid.
// Otherwise, return a point between v and min_q. // Otherwise, return a point between v and min_q.
if (min_distance == -1) { if (min_distance == -1)
{
return centroid(ear); return centroid(ear);
} else { }
else
{
return midpoint(v, min_q); return midpoint(v, min_q);
} }
} }