mirror of https://github.com/CGAL/cgal
1040 lines
32 KiB
C++
1040 lines
32 KiB
C++
// ======================================================================
|
|
//
|
|
// Copyright (c) The CGAL Consortium
|
|
//
|
|
// This software and related documentation is part of an INTERNAL release
|
|
// of the Computational Geometry Algorithms Library (CGAL). It is not
|
|
// intended for general use.
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// release : $CGAL_Revision: CGAL-2.3-I-24 $
|
|
// release_date : $CGAL_Date: 2000/12/29 $
|
|
//
|
|
// file : include/CGAL/Snap_rounding_2.h
|
|
// package : arr (1.73)
|
|
// maintainer : Eli Packer <elip@post.tau.ac.il>
|
|
// author(s) : Eli Packer
|
|
// coordinator : Tel-Aviv University (Dan Halperin <halperin@math.tau.ac.il>)
|
|
//
|
|
// ======================================================================
|
|
#ifndef CGAL_SR_2_H
|
|
#define CGAL_SR_2_H
|
|
|
|
#include <CGAL/leda_rational.h>
|
|
|
|
#include <iostream>
|
|
|
|
#ifndef CGAL_ENUM_H
|
|
#include <CGAL/enum.h>
|
|
#include <CGAL/predicates_on_points_2.h>
|
|
#include <CGAL/Random.h>
|
|
#include <CGAL/squared_distance_2.h>
|
|
#include <CGAL/point_generators_2.h>
|
|
#include <CGAL/intersection_2.h>
|
|
|
|
#endif
|
|
|
|
/*#ifndef SWEEP_TO_PRODUCE_PLANAR_MAP_SUBCURVES_H
|
|
#include <CGAL/sweep_to_produce_planar_map_subcurves.h>
|
|
#endif*/
|
|
|
|
//#include <CGAL/Sweep_line_tight_2.h>
|
|
#include <CGAL/Sweep_line_2.h>
|
|
|
|
//#ifndef CGAL_ARR_SEGMENT_TRAITS_2_H
|
|
#include <CGAL/Arr_segment_traits_2.h>
|
|
//#endif
|
|
|
|
#ifndef CGAL_ARR_POLYLINE_TRAITS_H
|
|
#include <CGAL/Arr_polyline_traits.h>
|
|
#endif
|
|
|
|
#ifdef ISR_DEBUG
|
|
#include <CGAL/IO/leda_window.h>
|
|
#endif
|
|
|
|
#include <list>
|
|
#include <set>
|
|
|
|
#include <CGAL/leda_real.h>
|
|
|
|
#include "../../include/CGAL/Snap_rounding_kd_2.h"
|
|
|
|
CGAL_BEGIN_NAMESPACE
|
|
|
|
#if defined(ISR_DEBUG)
|
|
typedef CGAL::Window_stream Window_stream;
|
|
#endif
|
|
|
|
template<class Rep_>
|
|
class Segment_data {
|
|
|
|
typedef Rep_ Rep;
|
|
typedef typename Rep::FT NT;
|
|
typedef CGAL::Segment_2<Rep> Segment_2;
|
|
typedef CGAL::Point_2<Rep> Point_2;
|
|
|
|
private:
|
|
NT x1;
|
|
NT y1;
|
|
NT x2;
|
|
NT y2;
|
|
|
|
public:
|
|
Segment_data();
|
|
Segment_data(NT inp_x1,NT inp_y1,NT inp_x2,NT inp_y2);
|
|
void debug() const;
|
|
NT get_x1();
|
|
NT get_y1();
|
|
NT get_x2();
|
|
NT get_y2();
|
|
inline void set_data(NT inp_x1,NT inp_y1,NT inp_x2,NT inp_y2);
|
|
void determine_direction();
|
|
bool equal(Segment_2 s);
|
|
};
|
|
|
|
template<class Rep_>
|
|
class Hot_Pixel {
|
|
|
|
typedef Rep_ Rep;
|
|
typedef typename Rep::FT NT;
|
|
typedef CGAL::Segment_2<Rep> Segment_2;
|
|
typedef CGAL::Point_2<Rep> Point_2;
|
|
|
|
private:
|
|
// (x,y) is the center of the hot pixel, prec is its edge length
|
|
NT x;
|
|
NT y;
|
|
NT prec;
|
|
Segment_2 *right_seg;
|
|
Segment_2 *left_seg;
|
|
Segment_2 *top_seg;
|
|
Segment_2 *bot_seg;
|
|
|
|
public:
|
|
void debug() const;
|
|
template<class Out>
|
|
void draw(Out &o) const;
|
|
Hot_Pixel(NT inp_x,NT inp_y,NT inp_prec);
|
|
~Hot_Pixel();
|
|
inline NT get_x() const;
|
|
inline NT get_y() const;
|
|
bool intersect_left(Segment_2 &seg) const;
|
|
bool intersect_right(Segment_2 &seg) const;
|
|
bool intersect_bot(Segment_2 &seg) const;
|
|
bool intersect_top(Segment_2 &seg) const;
|
|
bool intersect(Segment_data<Rep> &seg) const;
|
|
};
|
|
|
|
// a function for compare two hot pixels for the set of hot pixels
|
|
template<class Rep_>
|
|
struct hot_pixel_auclidian_cmp
|
|
{
|
|
bool operator()(const Hot_Pixel<Rep_> *h1,const Hot_Pixel<Rep_> *h2) const;
|
|
};
|
|
|
|
// a function for compare two hot pixels for the set of hot pixels a
|
|
// certain segment intersect
|
|
template<class Rep_>
|
|
struct hot_pixel_dir_cmp
|
|
{
|
|
bool operator ()(const Hot_Pixel<Rep_> *h1,const Hot_Pixel<Rep_> *h2);
|
|
};
|
|
|
|
|
|
template<class Rep_>
|
|
class Snap_rounding_2 {
|
|
|
|
typedef CGAL::Arr_segment_traits_2<Rep_ > Traits;
|
|
typedef Rep_ Rep;
|
|
typedef typename Rep::FT NT;
|
|
typedef typename Traits::X_curve X_curve;
|
|
typedef typename Traits::Curve Curve;
|
|
//typedef CGAL::Sweep_line_subcurve<Traits> SubCurve;
|
|
//typedef CGAL::Sweep_line_event<Traits, SubCurve> Event;
|
|
typedef std::list<X_curve> CurveContainer;
|
|
typedef typename CurveContainer::iterator CurveContainerIter;
|
|
|
|
public:
|
|
typedef CGAL::Segment_2<Rep> Segment_2;
|
|
typedef CGAL::Point_2<Rep> Point_2;
|
|
typedef std::list<Point_2> PointList;
|
|
typedef typename std::list<std::list<CGAL::Point_2<Rep> > >
|
|
Polylines_container;
|
|
typedef typename Polylines_container::const_iterator Polyline_const_iterator;
|
|
typedef typename Polylines_container::iterator Polyline_iterator;
|
|
typedef typename std::list<CGAL::Point_2<Rep> > Points_container;
|
|
typedef typename Points_container::const_iterator Point_const_iterator;
|
|
typedef typename std::list<Segment_2> Segments_container;
|
|
typedef typename Segments_container::const_iterator Segment_const_iterator;
|
|
typedef typename Segments_container::iterator Segment_iterator;
|
|
|
|
enum Direction {UP_RIGHT,UP_LEFT,DOWN_RIGHT,DOWN_LEFT,UP,DOWN,LEFT,
|
|
RIGHT,POINT_SEG};
|
|
|
|
static Direction seg_dir;
|
|
static bool erase_hp;
|
|
static inline Direction get_direction() {return(seg_dir);}
|
|
static inline void set_direction(Direction dir) {seg_dir = dir;}
|
|
static inline bool get_erase_hp() {return(erase_hp);}
|
|
|
|
Snap_rounding_2(Segment_const_iterator begin,
|
|
Segment_const_iterator end,
|
|
NT inp_prec,bool inp_do_isr = true,
|
|
int inp_number_of_kd_trees = default_number_of_kd_trees);
|
|
Snap_rounding_2(NT inp_prec,bool inp_do_isr = true,
|
|
int inp_number_of_kd_trees = default_number_of_kd_trees);
|
|
|
|
#ifdef ISR_DEBUG
|
|
template<class Out>
|
|
void output_distances(Out &o);
|
|
#endif
|
|
// !!!! change names to output ans input
|
|
const Polyline_const_iterator polylines_begin();
|
|
const Polyline_const_iterator polylines_end();
|
|
|
|
inline Segment_const_iterator segments_begin() const {
|
|
return(seg_2_list.begin());}
|
|
inline Segment_const_iterator segments_end() const {
|
|
return(seg_2_list.end());}
|
|
inline Segment_iterator segments_begin() {return(seg_2_list.begin());}
|
|
inline Segment_iterator segments_end() {return(seg_2_list.end());}
|
|
|
|
bool insert(Segment_2 seg);
|
|
bool push_back(Segment_2 seg);
|
|
template < class InputIterator >
|
|
int insert(InputIterator first, InputIterator last);
|
|
bool remove(Segment_2 seg);
|
|
void clear();
|
|
|
|
template<class Out>
|
|
void output(Out &o);
|
|
|
|
/*#ifdef ISR_DEBUG
|
|
void window_output(Window_stream &w,bool wait_for_click);
|
|
#endif*/
|
|
|
|
private:
|
|
// the next variable is for lazy evaluation:
|
|
// it determines whether an isr/sr work has
|
|
// to be done (at the beginning, after insertion, etc)
|
|
bool need_sr;
|
|
|
|
static const int default_number_of_kd_trees = 5;
|
|
|
|
std::set<Hot_Pixel<Rep> *,hot_pixel_auclidian_cmp<Rep> > hp_set;
|
|
NT prec,min_x,max_x,min_y,max_y;
|
|
Segments_container seg_2_list;
|
|
std::list<Segment_data<Rep> > seg_list;
|
|
std::list<std::list<Point_2> > segments_output_list;
|
|
int number_of_segments,number_of_kd_trees;
|
|
Multiple_kd_tree<NT,Hot_Pixel<Rep> *> *mul_kd_tree;
|
|
bool do_isr;
|
|
|
|
void find_hot_pixels_and_create_kd_trees();
|
|
void find_intersected_hot_pixels(Segment_data<Rep> &seg,
|
|
std::set<Hot_Pixel<Rep> *,
|
|
hot_pixel_dir_cmp<Rep> > &hot_pixels_intersected_set,
|
|
int &number_of_intersections);
|
|
|
|
void debug(std::set<Hot_Pixel<Rep>,hot_pixel_dir_cmp<Rep> > &s);
|
|
void reroute_sr(std::set<Hot_Pixel<Rep> *,hot_pixel_dir_cmp<Rep> >
|
|
&inp_hot_pixels_intersected_set,std::list<Point_2>
|
|
&seg_output);
|
|
void reroute_isr(std::set<Hot_Pixel<Rep> *,hot_pixel_dir_cmp<Rep> >
|
|
&inp_hot_pixels_intersected_set,std::list<Point_2>
|
|
&seg_output,int number_of_intersections,bool first_time);
|
|
void iterate();
|
|
};
|
|
|
|
#if defined(ISR_DEBUG) || defined(TEST)
|
|
#include <CGAL/squared_distance_2.h>
|
|
|
|
#endif
|
|
|
|
#ifdef ISR_DEBUG
|
|
int max_rec = 1,cur_rec = -1,cur_max,needed_hp = 0,unneeded_hp = 0;
|
|
#elif defined XXXX
|
|
int needed_hp = 0,unneeded_hp = 0;
|
|
#endif
|
|
|
|
template<class Rep_>
|
|
Segment_data<Rep_>::Segment_data() {}
|
|
template<class Rep_>
|
|
Segment_data<Rep_>::Segment_data(NT inp_x1,NT inp_y1,NT inp_x2,NT inp_y2) :
|
|
x1(inp_x1),y1(inp_y1),x2(inp_x2),y2(inp_y2) {}
|
|
|
|
template<class Rep_>
|
|
void Segment_data<Rep_>::debug() const {std::cerr << "Segment (" << x1 << ","
|
|
<< y1 << "):(" << x2 << ":" << y2 << ")\n";}
|
|
|
|
template<class Rep_>
|
|
typename Rep_::FT Segment_data<Rep_>::get_x1() {return(x1);}
|
|
|
|
template<class Rep_>
|
|
typename Rep_::FT Segment_data<Rep_>::get_y1() {return(y1);}
|
|
|
|
template<class Rep_>
|
|
typename Rep_::FT Segment_data<Rep_>::get_x2() {return(x2);}
|
|
|
|
template<class Rep_>
|
|
typename Rep_::FT Segment_data<Rep_>::get_y2() {return(y2);}
|
|
|
|
template<class Rep_>
|
|
inline void Segment_data<Rep_>::set_data(NT inp_x1,NT inp_y1,NT inp_x2,
|
|
NT inp_y2)
|
|
{
|
|
x1 = inp_x1;
|
|
y1 = inp_y1;
|
|
x2 = inp_x2;
|
|
y2 = inp_y2;
|
|
}
|
|
|
|
template<class Rep_>
|
|
bool Segment_data<Rep_>::equal(Segment_2 s)
|
|
{
|
|
return(
|
|
s.source().x() == x1 &
|
|
s.source().y() == y1 &
|
|
s.target().x() == x2 &
|
|
s.target().y() == y2);
|
|
}
|
|
|
|
template<class Rep_>
|
|
void Segment_data<Rep_>::determine_direction()
|
|
{
|
|
if(x1 < x2) {
|
|
if(y1 < y2)
|
|
Snap_rounding_2<Rep_>::set_direction(Snap_rounding_2<Rep_>::UP_RIGHT);
|
|
else if(y1 == y2)
|
|
Snap_rounding_2<Rep_>::set_direction(Snap_rounding_2<Rep_>::RIGHT);
|
|
else
|
|
Snap_rounding_2<Rep_>::set_direction(Snap_rounding_2<Rep_>::DOWN_RIGHT);
|
|
} else if(x1 == x2) {
|
|
if(y1 < y2)
|
|
Snap_rounding_2<Rep_>::set_direction(Snap_rounding_2<Rep_>::UP);
|
|
else if(y1 == y2)
|
|
Snap_rounding_2<Rep_>::set_direction(Snap_rounding_2<Rep_>::POINT_SEG);
|
|
else
|
|
Snap_rounding_2<Rep_>::set_direction(Snap_rounding_2<Rep_>::DOWN);
|
|
} else {
|
|
if(y1 < y2)
|
|
Snap_rounding_2<Rep_>::set_direction(Snap_rounding_2<Rep_>::UP_LEFT);
|
|
else if(y1 == y2)
|
|
Snap_rounding_2<Rep_>::set_direction(Snap_rounding_2<Rep_>::LEFT);
|
|
else
|
|
Snap_rounding_2<Rep_>::set_direction(Snap_rounding_2<Rep_>::DOWN_LEFT);
|
|
}
|
|
}
|
|
|
|
|
|
template<class Rep_>
|
|
void Hot_Pixel<Rep_>::debug() const {std::cerr << "Hot Pixel (" << x << ":"
|
|
<< y << ")\n";}
|
|
|
|
template<class Rep_>
|
|
template<class Out> void Hot_Pixel<Rep_>::draw(Out &o) const
|
|
{
|
|
o << *right_seg;
|
|
o << *left_seg;
|
|
o << *top_seg;
|
|
o << *bot_seg;
|
|
}
|
|
|
|
// intersection pixel
|
|
template<class Rep_>
|
|
Hot_Pixel<Rep_>::Hot_Pixel(NT inp_x,NT inp_y,NT inp_prec) : prec(inp_prec)
|
|
{
|
|
x = NT(floor((inp_x / prec).to_double())) * prec + prec / 2.0;
|
|
|
|
y = NT(floor((inp_y / prec).to_double())) * prec + prec / 2.0;
|
|
|
|
right_seg = new Segment_2(Point_2(x + prec / 2.0,y - prec / 2.0),
|
|
Point_2(x + prec / 2.0,y + prec / 2.0));
|
|
left_seg = new Segment_2(Point_2(x - prec / 2.0,y - prec / 2.0),
|
|
Point_2(x - prec / 2.0,y + prec / 2.0));
|
|
top_seg = new Segment_2(Point_2(x - prec / 2.0,y + prec / 2.0),
|
|
Point_2(x + prec / 2.0,y + prec / 2.0));
|
|
bot_seg = new Segment_2(Point_2(x - prec / 2.0,y - prec / 2.0),
|
|
Point_2(x + prec / 2.0,y - prec / 2.0));
|
|
}
|
|
|
|
template<class Rep_>
|
|
Hot_Pixel<Rep_>::~Hot_Pixel()
|
|
{
|
|
if(Snap_rounding_2<Rep_>::get_erase_hp()) {
|
|
delete(right_seg);
|
|
delete(left_seg);
|
|
delete(top_seg);
|
|
delete(bot_seg);
|
|
}
|
|
}
|
|
|
|
template<class Rep_>
|
|
inline typename Rep_::FT Hot_Pixel<Rep_>::get_x() const {return(x);}
|
|
|
|
template<class Rep_>
|
|
inline typename Rep_::FT Hot_Pixel<Rep_>::get_y() const {return(y);}
|
|
|
|
template<class Rep_>
|
|
bool Hot_Pixel<Rep_>::intersect_left(Segment_2 &seg) const
|
|
{
|
|
CGAL::Object result;
|
|
Point_2 p;
|
|
Segment_2 s;
|
|
|
|
result = CGAL::intersection(seg,*left_seg);
|
|
|
|
if(CGAL::assign(p,result)) {
|
|
NT tmp = y + prec / 2.0;
|
|
return(p.y() != tmp || Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::UP_LEFT && seg.source().y() != tmp ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::DOWN_RIGHT && seg.target().y() != tmp);
|
|
} else if(CGAL::assign(s,result))
|
|
return(true);
|
|
else
|
|
return(false);
|
|
}
|
|
|
|
|
|
template<class Rep_>
|
|
bool Hot_Pixel<Rep_>::intersect_right(Segment_2 &seg) const
|
|
{
|
|
CGAL::Object result;
|
|
Point_2 p;
|
|
Segment_2 s;
|
|
|
|
result = CGAL::intersection(seg,*right_seg);
|
|
|
|
if(CGAL::assign(p,result)) {
|
|
// bottom right point was checked in intersect_bot
|
|
|
|
NT tmp = y + prec / 2.0;
|
|
if(p.y() == tmp)
|
|
return(Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::UP_RIGHT && seg.source().y() != tmp ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::DOWN_LEFT && seg.target().y() != tmp);
|
|
else if(p.y() == y - prec / 2.0)
|
|
return(false);// was checked
|
|
else
|
|
return((Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::LEFT ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::DOWN_LEFT ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::UP_LEFT) && seg.target().x() !=
|
|
x + prec / 2.0 ||
|
|
(Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::RIGHT ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::DOWN_RIGHT ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::UP_RIGHT) && seg.source().x() !=
|
|
x + prec / 2.0);
|
|
} else
|
|
return(false);
|
|
}
|
|
|
|
template<class Rep_>
|
|
bool Hot_Pixel<Rep_>::intersect_bot(Segment_2 &seg) const
|
|
{
|
|
CGAL::Object result;
|
|
Point_2 p;
|
|
Segment_2 s;
|
|
|
|
result = CGAL::intersection(seg,*bot_seg);
|
|
|
|
if(CGAL::assign(p,result)) {
|
|
NT tmp = x + prec / 2.0;
|
|
return(p.x() != tmp || Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::UP_LEFT && seg.target().x() != tmp ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::DOWN_RIGHT && seg.source().x() != tmp);
|
|
} else if(CGAL::assign(s,result))
|
|
return(true);
|
|
else
|
|
return(false);
|
|
}
|
|
|
|
template<class Rep_>
|
|
bool Hot_Pixel<Rep_>::intersect_top(Segment_2 &seg) const
|
|
{
|
|
CGAL::Object result;
|
|
Point_2 p;
|
|
Segment_2 s;
|
|
|
|
result = CGAL::intersection(seg,*top_seg);
|
|
|
|
if(CGAL::assign(p,result)) {
|
|
// corner points was checked in intersect_bot
|
|
NT tar_y = seg.target().y(),sou_y = seg.source().y();
|
|
|
|
if(p.x() == x - prec / 2.0 || p.x() == x + prec / 2.0)
|
|
return(false);// were checked
|
|
else
|
|
return((Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::DOWN ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::DOWN_LEFT ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::DOWN_RIGHT) && tar_y != y + prec / 2.0 ||
|
|
(Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::UP ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::UP_LEFT ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::UP_RIGHT) && sou_y != y + prec / 2.0);
|
|
} else
|
|
return(false);
|
|
}
|
|
|
|
template<class Rep_>
|
|
bool Hot_Pixel<Rep_>::intersect(Segment_data<Rep_> &seg) const
|
|
{
|
|
Segment_2 s(Point_2(seg.get_x1(),seg.get_y1()),Point_2(seg.get_x2(),
|
|
seg.get_y2()));
|
|
|
|
return(intersect_bot(s) || intersect_left(s) || intersect_right(s) ||
|
|
intersect_top(s));
|
|
}
|
|
|
|
// a function for compare two hot pixels for the set of hot pixels
|
|
template<class Rep_>
|
|
bool hot_pixel_auclidian_cmp<Rep_>::operator()(const Hot_Pixel<Rep_> *h1,
|
|
const Hot_Pixel<Rep_> *h2) const
|
|
{
|
|
return(h1->get_x() < h2->get_x() ||
|
|
h1->get_x() == h2->get_x() && h1->get_y() < h2->get_y());
|
|
}
|
|
|
|
// a function for compare two hot pixels for the set of hot pixels a certain
|
|
// segment intersect
|
|
template<class Rep_>
|
|
bool hot_pixel_dir_cmp<Rep_>::operator ()(const Hot_Pixel<Rep_> *h1,\
|
|
const Hot_Pixel<Rep_> *h2)
|
|
{
|
|
return(
|
|
// Point segment intersects only one pixel, thus ignored
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::UP_RIGHT &&
|
|
(h1->get_x() < h2->get_x() ||
|
|
h1->get_x() == h2->get_x() && h1->get_y() < h2->get_y()) ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::UP_LEFT &&
|
|
(h1->get_x() > h2->get_x() ||
|
|
h1->get_x() == h2->get_x() && h1->get_y() < h2->get_y()) ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::DOWN_RIGHT &&
|
|
(h1->get_x() < h2->get_x() ||
|
|
h1->get_x() == h2->get_x() && h1->get_y() > h2->get_y()) ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::DOWN_LEFT &&
|
|
(h1->get_x() > h2->get_x() ||
|
|
h1->get_x() == h2->get_x() && h1->get_y() > h2->get_y()) ||
|
|
Snap_rounding_2<Rep_>::get_direction() == Snap_rounding_2<Rep_>::UP &&
|
|
h1->get_y() < h2->get_y() ||
|
|
Snap_rounding_2<Rep_>::get_direction() == Snap_rounding_2<Rep_>::DOWN &&
|
|
h1->get_y() > h2->get_y() ||
|
|
Snap_rounding_2<Rep_>::get_direction() == Snap_rounding_2<Rep_>::LEFT &&
|
|
h1->get_x() > h2->get_x() ||
|
|
Snap_rounding_2<Rep_>::get_direction() ==
|
|
Snap_rounding_2<Rep_>::RIGHT &&
|
|
h1->get_x() < h2->get_x());
|
|
}
|
|
|
|
|
|
|
|
template<class Rep_>
|
|
void Snap_rounding_2<Rep_>::find_hot_pixels_and_create_kd_trees()
|
|
{
|
|
Hot_Pixel<Rep_> *hp;
|
|
typename std::list<Segment_data<Rep_> >::iterator iter1;
|
|
CGAL::Object result;
|
|
Point_2 p;
|
|
std::list<std::pair<std::pair<NT,NT>,Hot_Pixel<Rep_> *> > hot_pixels_list;
|
|
|
|
list<X_curve> segments;
|
|
for(iter1 = seg_list.begin();iter1 != seg_list.end();++iter1)
|
|
segments.push_back(X_curve(Point_2(iter1->get_x1(),iter1->get_y1()),
|
|
Point_2(iter1->get_x2(),iter1->get_y2())));
|
|
|
|
// PM pm(new CGAL::Pm_naive_point_location<PM>);
|
|
// sweep_to_construct_planar_map(segments.begin(), segments.end(), pm);
|
|
std::list<X_curve> subcurves;
|
|
|
|
/* sweep_to_produce_planar_map_subcurves(segments.begin(),
|
|
segments.end(),
|
|
traits,
|
|
subcurves);*/
|
|
|
|
/*// get subcurves with overlapping
|
|
// CGAL::Sweep_line_tight_2<CurveContainerIter, Traits, Event, SubCurve> sl;
|
|
CGAL::Sweep_line_2<CurveContainerIter, Traits> sl;
|
|
sl.get_subcurves(segments.begin(), segments.end(),
|
|
std::back_inserter(subcurves));*/
|
|
|
|
// get intersection points (with endpoints)
|
|
PointList mypointlist;
|
|
// CGAL::Sweep_line_tight_2<CurveContainerIter, Traits,
|
|
// Event, SubCurve> sl;
|
|
CGAL::Sweep_line_2<CurveContainerIter, Traits> sl;
|
|
sl.get_intersection_points(segments.begin(), segments.end(),
|
|
std::back_inserter(mypointlist));
|
|
|
|
for(typename std::list<Point_2>::const_iterator
|
|
v_iter = mypointlist.begin();
|
|
v_iter != mypointlist.end();++v_iter) {
|
|
hp = new Hot_Pixel<Rep_>(v_iter->x(),v_iter->y(),prec);
|
|
hot_pixels_list.push_back(std::pair<std::pair<NT,NT>,Hot_Pixel<Rep_> *>(
|
|
std::pair<NT,NT>(hp->get_x(),hp->get_y()),hp));
|
|
}
|
|
|
|
/* for(list<X_curve>::iterator v_iter = subcurves.begin();
|
|
v_iter != subcurves.end();
|
|
++v_iter) {
|
|
hp = new Hot_Pixel<Rep_>(v_iter->source().x(),v_iter->source().y(),prec);
|
|
if(hp_set.insert(hp).second)
|
|
hot_pixels_list.push_back(pair<pair<NT,NT>,Hot_Pixel<Rep_> *>(
|
|
pair<NT,NT>(hp->get_x(),hp->get_y()),hp));
|
|
hp = new Hot_Pixel<Rep_>(v_iter->target().x(),v_iter->target().y(),prec);
|
|
if(hp_set.insert(hp).second)
|
|
hot_pixels_list.push_back(pair<pair<NT,NT>,Hot_Pixel<Rep_> *>(
|
|
pair<NT,NT>(hp->get_x(),hp->get_y()),hp));
|
|
}*/
|
|
|
|
// create kd multiple tree
|
|
// create simple_list from seg_list
|
|
std::list<std::pair<std::pair<NT,NT>,std::pair<NT,NT> > > simple_seg_list;
|
|
for(typename std::list<Segment_data<Rep_> >::iterator iter =
|
|
seg_list.begin();iter != seg_list.end();++iter) {
|
|
std::pair<NT,NT> first(iter->get_x1(),iter->get_y1()),
|
|
second(iter->get_x2(),iter->get_y2());
|
|
simple_seg_list.push_back(std::pair<std::pair<NT,NT>,std::pair<NT,NT> >(
|
|
first,second));
|
|
}
|
|
|
|
mul_kd_tree = new Multiple_kd_tree<NT,Hot_Pixel<Rep_> *>(hot_pixels_list,
|
|
number_of_kd_trees,simple_seg_list);
|
|
}
|
|
|
|
template<class Rep_>
|
|
void Snap_rounding_2<Rep_>::find_intersected_hot_pixels(Segment_data<Rep_>
|
|
&seg,
|
|
std::set<Hot_Pixel<Rep_> *,
|
|
hot_pixel_dir_cmp<Rep_> > &hot_pixels_intersected_set,
|
|
int &number_of_intersections)
|
|
{
|
|
typename std::list<Hot_Pixel<Rep_> *>::iterator iter;
|
|
|
|
hot_pixels_intersected_set.clear();
|
|
seg.determine_direction();
|
|
number_of_intersections = 0;
|
|
|
|
std::list<Hot_Pixel<Rep_> *> hot_pixels_list;
|
|
mul_kd_tree->get_intersecting_points(hot_pixels_list,
|
|
Segment_2(Point_2(seg.get_x1(),seg.get_y1()),
|
|
Point_2(seg.get_x2(),seg.get_y2())),prec);
|
|
|
|
for(iter = hot_pixels_list.begin();iter != hot_pixels_list.end();++iter) {
|
|
if((*iter)->intersect(seg)) {
|
|
|
|
#if defined ISR_DEBUG
|
|
++needed_hp;
|
|
#endif
|
|
hot_pixels_intersected_set.insert(*iter);
|
|
}
|
|
#if defined ISR_DEBUG
|
|
else
|
|
++unneeded_hp;
|
|
#endif
|
|
}
|
|
|
|
number_of_intersections = hot_pixels_intersected_set.size();
|
|
}
|
|
|
|
template<class Rep_>
|
|
void debug(std::set<Hot_Pixel<Rep_>,hot_pixel_dir_cmp<Rep_> > &s)
|
|
{
|
|
std::cerr << " Debugging inp_hot_pixels_intersected_set\n";
|
|
for(typename std::set<Hot_Pixel<Rep_>,hot_pixel_dir_cmp<Rep_> >::
|
|
iterator iter = s.begin();iter != s.end();++iter) {
|
|
std::cerr << " ";
|
|
iter->debug();
|
|
}
|
|
std::cerr << " Finish Debugging inp_hot_pixels_intersected_set\n";
|
|
}
|
|
|
|
template<class Rep_>
|
|
void Snap_rounding_2<Rep_>::reroute_sr(std::set<Hot_Pixel<Rep_> *,
|
|
hot_pixel_dir_cmp<Rep_> > &inp_hot_pixels_intersected_set,
|
|
std::list<Point_2> &seg_output)
|
|
{
|
|
typename std::set<Hot_Pixel<Rep_> *,
|
|
hot_pixel_dir_cmp<Rep_> >::iterator hot_pixel_iter =
|
|
inp_hot_pixels_intersected_set.begin();
|
|
++hot_pixel_iter;
|
|
|
|
while(hot_pixel_iter != inp_hot_pixels_intersected_set.end()) {
|
|
seg_output.push_back(Point_2((*hot_pixel_iter)->get_x(),
|
|
(*hot_pixel_iter)->get_y()));
|
|
++hot_pixel_iter;
|
|
}
|
|
|
|
}
|
|
|
|
template<class Rep_>
|
|
void Snap_rounding_2<Rep_>::reroute_isr(std::set<Hot_Pixel<Rep_> *,
|
|
hot_pixel_dir_cmp<Rep_> > &inp_hot_pixels_intersected_set,
|
|
std::list<Point_2> &seg_output,int number_of_intersections,bool first_time)
|
|
{
|
|
typename std::set<Hot_Pixel<Rep_> *,hot_pixel_dir_cmp<Rep_> >::
|
|
iterator hot_pixel_iter,next_hot_pixel_iter,before_last_hot_pixel_iter;
|
|
Segment_data<Rep_> seg;
|
|
std::set<Hot_Pixel<Rep_> *,hot_pixel_dir_cmp<Rep_> >
|
|
hot_pixels_intersected_set;
|
|
|
|
if(number_of_intersections > 2 || first_time) {
|
|
before_last_hot_pixel_iter = inp_hot_pixels_intersected_set.end();
|
|
--before_last_hot_pixel_iter;
|
|
|
|
for(hot_pixel_iter = inp_hot_pixels_intersected_set.begin();
|
|
hot_pixel_iter != before_last_hot_pixel_iter;++hot_pixel_iter) {
|
|
next_hot_pixel_iter = hot_pixel_iter;
|
|
++next_hot_pixel_iter;
|
|
seg.set_data((*hot_pixel_iter)->get_x(),(*hot_pixel_iter)->get_y(),
|
|
(*next_hot_pixel_iter)->get_x(),(*next_hot_pixel_iter)->get_y());
|
|
seg.determine_direction();
|
|
find_intersected_hot_pixels(seg,hot_pixels_intersected_set,
|
|
number_of_intersections);
|
|
reroute_isr(hot_pixels_intersected_set,seg_output,
|
|
number_of_intersections,false);
|
|
}
|
|
} else {
|
|
// insert second hot pixel
|
|
hot_pixel_iter = inp_hot_pixels_intersected_set.begin();
|
|
++hot_pixel_iter;
|
|
seg_output.push_back(Point_2((*hot_pixel_iter)->get_x(),
|
|
(*hot_pixel_iter)->get_y()));
|
|
}
|
|
}
|
|
|
|
|
|
template<class Rep_>
|
|
void Snap_rounding_2<Rep_>::iterate()
|
|
{
|
|
std::list<Point_2> seg_output;
|
|
std::set<Hot_Pixel<Rep_> *,hot_pixel_dir_cmp<Rep_> >
|
|
hot_pixels_intersected_set;
|
|
typename std::set<Hot_Pixel<Rep_> *,hot_pixel_dir_cmp<Rep_> >::
|
|
iterator hot_pixel_iter;
|
|
int number_of_intersections;
|
|
Hot_Pixel<Rep_> *hp;
|
|
|
|
for(typename std::list<Segment_data<Rep_> >::iterator iter =
|
|
seg_list.begin();iter != seg_list.end();++iter) {
|
|
seg_output.clear();
|
|
iter->determine_direction();
|
|
find_intersected_hot_pixels(*iter,hot_pixels_intersected_set,
|
|
number_of_intersections);
|
|
|
|
// hot_pixels_intersected_set must have at least two hot pixels when the
|
|
// segment is not in entirely inside a hot pixel enter first hot pixel
|
|
hot_pixel_iter = hot_pixels_intersected_set.begin();
|
|
if(hot_pixel_iter == hot_pixels_intersected_set.end()) {
|
|
// segment entirely inside a pixel
|
|
hp = new Hot_Pixel<Rep_>(iter->get_x1(),iter->get_y1(),prec);
|
|
seg_output.push_back(Point_2(hp->get_x(),hp->get_y()));
|
|
erase_hp = true;
|
|
delete(hp);
|
|
erase_hp = false;
|
|
} else {
|
|
seg_output.push_back(Point_2((*hot_pixel_iter)->get_x(),
|
|
(*hot_pixel_iter)->get_y()));
|
|
if(number_of_intersections > 1) {
|
|
// segments that have at most one intersecting hot pixel are
|
|
// done(it was inserted)
|
|
if(do_isr)
|
|
reroute_isr(hot_pixels_intersected_set,seg_output,
|
|
number_of_intersections,true);
|
|
else
|
|
reroute_sr(hot_pixels_intersected_set,seg_output);
|
|
}
|
|
}
|
|
|
|
segments_output_list.push_back(seg_output);
|
|
}
|
|
}
|
|
|
|
template<class Rep_>
|
|
/*Snap_rounding_2<Rep_>::Snap_rounding_2(Segment_const_iterator
|
|
begin,Segment_const_iterator end,
|
|
NT inp_prec,bool inp_do_isr = true,int inp_number_of_kd_trees =
|
|
default_number_of_kd_trees)*/
|
|
Snap_rounding_2<Rep_>::Snap_rounding_2(Segment_const_iterator
|
|
begin,Segment_const_iterator end,
|
|
NT inp_prec,bool inp_do_isr,int inp_number_of_kd_trees)
|
|
{
|
|
// initialize approximation angles map
|
|
|
|
erase_hp = false;
|
|
do_isr = inp_do_isr;
|
|
prec = inp_prec;
|
|
number_of_segments = 0;
|
|
number_of_kd_trees = inp_number_of_kd_trees;
|
|
need_sr = true;
|
|
// copy segments list
|
|
while(begin != end) {
|
|
seg_list.push_back(Segment_data<Rep_>(begin->source().x(),
|
|
begin->source().y(),begin->target().x(),
|
|
begin->target().y()));
|
|
seg_2_list.push_back(*begin);
|
|
++number_of_segments;
|
|
++begin;
|
|
}
|
|
|
|
// !!!!! lazy evaluation
|
|
/* find_hot_pixels_and_create_kd_trees();
|
|
iterate();*/
|
|
}
|
|
|
|
template<class Rep_>
|
|
Snap_rounding_2<Rep_>::Snap_rounding_2(
|
|
NT inp_prec,bool inp_do_isr,int inp_number_of_kd_trees)
|
|
{
|
|
// initialize approximation angles map
|
|
need_sr = true;
|
|
erase_hp = false;
|
|
do_isr = inp_do_isr;
|
|
prec = inp_prec;
|
|
number_of_segments = 0;
|
|
number_of_kd_trees = inp_number_of_kd_trees;
|
|
}
|
|
|
|
template<class Rep_>
|
|
bool Snap_rounding_2<Rep_>::insert(Segment_2 seg)
|
|
{
|
|
need_sr = true;
|
|
seg_list.push_back(Segment_data<Rep_>(
|
|
seg.source().x(),
|
|
seg.source().y(),
|
|
seg.target().x(),
|
|
seg.target().y()));
|
|
|
|
seg_2_list.push_back(seg);
|
|
++number_of_segments;
|
|
|
|
return(true);
|
|
}
|
|
|
|
template<class Rep_>
|
|
bool Snap_rounding_2<Rep_>::push_back(Segment_2 seg)
|
|
{
|
|
return(insert(seg));
|
|
}
|
|
|
|
template < class Rep_ >
|
|
template < class InputIterator >
|
|
int
|
|
Snap_rounding_2<Rep_>::insert(InputIterator first, InputIterator last)
|
|
{
|
|
need_sr = true;
|
|
int n = 0;
|
|
while(first != last){
|
|
if(insert(*first)){
|
|
n++;
|
|
}
|
|
++first;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
|
|
template<class Rep_>
|
|
const Snap_rounding_2<Rep_>::Polyline_const_iterator
|
|
Snap_rounding_2<Rep_>::polylines_begin()
|
|
{
|
|
if(need_sr) {
|
|
need_sr = false;
|
|
find_hot_pixels_and_create_kd_trees();
|
|
iterate();
|
|
}
|
|
|
|
return(segments_output_list.begin());
|
|
}
|
|
|
|
template<class Rep_>
|
|
const Snap_rounding_2<Rep_>::Polyline_const_iterator
|
|
Snap_rounding_2<Rep_>::polylines_end()
|
|
{
|
|
if(need_sr) {
|
|
need_sr = false;
|
|
find_hot_pixels_and_create_kd_trees();
|
|
iterate();
|
|
}
|
|
|
|
return(segments_output_list.end());
|
|
}
|
|
|
|
template<class Rep_>
|
|
bool Snap_rounding_2<Rep_>::remove(Segment_2 seg)
|
|
{
|
|
need_sr = true;
|
|
bool found = false;
|
|
Segment_data<Rep> s;
|
|
|
|
for(std::list<Segment_data<Rep> >::iterator i1 = seg_list.begin();
|
|
i1 != seg_list.end();++i1) {
|
|
s = *i1;
|
|
if(s.equal(seg)) {
|
|
found = true;
|
|
seg_list.erase(i1);
|
|
--number_of_segments;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(found) {
|
|
for(Segment_iterator i2 = seg_2_list.begin();
|
|
i2 != seg_2_list.end();++i2) {
|
|
if(seg == *i2) {
|
|
seg_2_list.erase(i2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(found);
|
|
}
|
|
|
|
template<class Rep_>
|
|
void Snap_rounding_2<Rep_>::clear()
|
|
{
|
|
need_sr = true;
|
|
seg_list.clear();
|
|
seg_2_list.clear();
|
|
}
|
|
|
|
template<class Rep_>
|
|
template<class Out> void Snap_rounding_2<Rep_>::output(Out &o)
|
|
{
|
|
o << number_of_segments << std::endl;
|
|
for(typename std::list<std::list<Point_2> >::iterator iter1 =
|
|
segments_output_list.begin();iter1 != segments_output_list.end();
|
|
++iter1) {
|
|
for(typename std::list<Point_2>::iterator iter2 = iter1->begin();
|
|
iter2 != iter1->end();++iter2)
|
|
o << iter2->x().to_double() << " " << iter2->y().to_double() << " ";
|
|
|
|
o << std::endl;
|
|
}
|
|
}
|
|
|
|
/*#ifdef ISR_DEBUG
|
|
template<class Rep_>
|
|
template<class Out> void Snap_rounding_2<Rep_>::output_distances(Out &o)
|
|
{
|
|
double max = 0,max_seg_dis,evarage_dis,cur_dis;
|
|
typename std::list<Segment_data<Rep_> >::iterator
|
|
orig_iter = seg_list.begin();
|
|
|
|
for(typename std::list<std::list<std::pair<NT,NT> > >::iterator iter1 =
|
|
segments_output_list.begin();iter1 != segments_output_list.end();
|
|
++iter1) {
|
|
max_seg_dis = 0;
|
|
for(typename std::list<std::pair<NT,NT> >::iterator
|
|
iter2 = iter1->begin();
|
|
iter2 != iter1->end();++iter2) {
|
|
cur_dis = sqrt(CGAL::squared_distance(Point_2(iter2->first,
|
|
iter2->second),Segment_2(Point_2(orig_iter->get_x1(),
|
|
orig_iter->get_y1()),Point_2(orig_iter->get_x2(),
|
|
orig_iter->get_y2()))).to_double());
|
|
if(cur_dis > max_seg_dis)
|
|
max_seg_dis = cur_dis;
|
|
}
|
|
|
|
evarage_dis += max_seg_dis;
|
|
if(max_seg_dis > max)
|
|
max = max_seg_dis;
|
|
|
|
++orig_iter;
|
|
}
|
|
evarage_dis /= seg_list.size();
|
|
|
|
std::cerr << "max distance between output and original is " << max << endl;
|
|
std::cerr << "evarage distance between output and original is " <<
|
|
evarage_dis << endl;
|
|
}
|
|
|
|
|
|
template<class Rep_>
|
|
void Snap_rounding_2<Rep_>::window_output(Window_stream &w,bool wait_for_click)
|
|
{
|
|
double x,y;
|
|
bool seg_painted;
|
|
|
|
w << CGAL::BLACK;
|
|
|
|
for(typename std::set<Hot_Pixel<Rep_> *,hot_pixel_auclidian_cmp<Rep_> >::
|
|
iterator iter = hp_set.begin();
|
|
iter != hp_set.end();++iter)
|
|
(*iter)->draw(w);
|
|
|
|
// draw original segments
|
|
w << CGAL::BLACK;
|
|
for(typename std::list<Segment_data<Rep_> >::iterator iter =
|
|
seg_list.begin();iter != seg_list.end();++iter) {
|
|
if(iter->get_x1() == iter->get_x2() && iter->get_y1() == iter->get_y2())
|
|
w << Point_2(iter->get_x1(),iter->get_y1());
|
|
else
|
|
w << Segment_2(Point_2(iter->get_x1(),iter->get_y1()),
|
|
Point_2(iter->get_x2(),iter->get_y2()));
|
|
}
|
|
std::cerr << "r222222\n";
|
|
// draw isr polylines
|
|
w << CGAL::RED;
|
|
typename std::list<Point_2>::iterator iter2,iter3;
|
|
std::cerr << "r33333\n";
|
|
for(typename std::list<std::list<Point_2> >::iterator iter1 =
|
|
segments_output_list.begin();iter1 != segments_output_list.end();
|
|
++iter1) {
|
|
std::cerr << "r44444\n";
|
|
if(wait_for_click)
|
|
w.read_mouse(x,y);
|
|
iter2 = iter3 = iter1->begin();
|
|
seg_painted = false;
|
|
for(++iter2;iter2 != iter1->end();++iter2) {
|
|
std::cerr << "r5555\n";
|
|
seg_painted = true;
|
|
w << Segment_2(*iter2,*iter3);
|
|
++iter3;
|
|
}
|
|
|
|
if(!seg_painted) { // segment entirely inside hot pixel
|
|
--iter2;
|
|
w << *iter2;
|
|
}
|
|
}
|
|
|
|
int mouse_input;
|
|
while(true) {
|
|
mouse_input = w.read_mouse(x,y);
|
|
if(mouse_input == 1)
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
*/
|
|
|
|
template<class Rep>
|
|
typename Snap_rounding_2<Rep>::Direction Snap_rounding_2<Rep>::seg_dir;
|
|
|
|
template<class Rep>
|
|
bool Snap_rounding_2<Rep>::erase_hp = false;
|
|
|
|
CGAL_END_NAMESPACE
|
|
|
|
#endif // CGAL_ISR_2_H
|