mirror of https://github.com/CGAL/cgal
Snap of polygons
This commit is contained in:
parent
64922a63bb
commit
c380ad2fb6
|
|
@ -476,12 +476,12 @@ typename OutputContainer::iterator compute_snapped_subcurves_2(InputIterator
|
|||
using I2E = typename Traits::Converter_in;
|
||||
using E2O = typename Traits::Converter_out;
|
||||
using VectorIterator = typename std::vector<Segment_2>::iterator;
|
||||
I2E converter_to_exact=traits.converter_to_exact_object();
|
||||
E2O converter_from_exact=traits.converter_from_exact_object();
|
||||
I2E to_exact=traits.converter_to_exact_object();
|
||||
E2O from_exact=traits.converter_from_exact_object();
|
||||
|
||||
std::vector<Segment_2> convert_input;
|
||||
for(InputIterator it=input_begin; it!=input_end; ++it)
|
||||
convert_input.push_back(Segment_2(converter_to_exact(*it)));
|
||||
convert_input.push_back(Segment_2(to_exact(*it)));
|
||||
std::vector<Segment_2> segs;
|
||||
#ifdef DOUBLE_2D_SNAP_VERBOSE
|
||||
std::cout << "Solved intersections" << std::endl;
|
||||
|
|
@ -537,7 +537,7 @@ typename OutputContainer::iterator compute_snapped_subcurves_2(InputIterator
|
|||
set_out_segs.emplace((std::min)(poly[i-1],poly[i]),(std::max)(poly[i-1],poly[i]));
|
||||
}
|
||||
for(auto &pair: set_out_segs){
|
||||
output.emplace_back(converter_from_exact(pts[pair.first]), converter_from_exact(pts[pair.second]));
|
||||
output.emplace_back(from_exact(pts[pair.first]), from_exact(pts[pair.second]));
|
||||
assert(pts[pair.first]!=pts[pair.second]);
|
||||
}
|
||||
|
||||
|
|
@ -547,71 +547,67 @@ typename OutputContainer::iterator compute_snapped_subcurves_2(InputIterator
|
|||
/**
|
||||
* ingroup
|
||||
*
|
||||
* Given a range of segments, compute rounded subsegments that are pairwise disjoint in their interior, as induced by the input curves.
|
||||
* Given a Polygon_2, compute rounded segments that are pairwise disjoint in their interior, as induced by the input polygon.
|
||||
* The output is guarantee to be a Polygon but may present pinched section.
|
||||
*
|
||||
* @tparam Concurrency_tag That template parameter enables to choose whether the algorithm is to be run in
|
||||
* parallel, if CGAL::Parallel_tag is specified and CGAL has been linked with the Intel TBB library, or sequentially, if CGAL::Sequential_tag - the default value - is specified.
|
||||
* @tparam InputIterator iterator of a segment range
|
||||
* @tparam OutputContainer inserter of a segment range
|
||||
* @tparam The exact kernel needed for computation (Epeck by default)
|
||||
*
|
||||
* @warning The convex property is not necessarly preserved
|
||||
*/
|
||||
template <class Concurrency_tag=Sequential_tag, class InputIterator , class OutputContainer, class Traits=Float_snap_rounding_traits_2<typename Kernel_traits<std::remove_cv_t<typename std::iterator_traits<InputIterator>::value_type>>::Kernel> >
|
||||
typename OutputContainer::iterator snap_polygons_2(InputIterator input_begin,
|
||||
InputIterator input_end,
|
||||
OutputContainer& output,
|
||||
const Traits& traits=Traits())
|
||||
template <class Concurrency_tag=Sequential_tag, class Polygon_2, class Traits=Float_snap_rounding_traits_2<typename Kernel_traits<typename Polygon_2::Point_2>::Kernel> >
|
||||
void snap_polygons_2(const Polygon_2 &P,
|
||||
Polygon_2 &out,
|
||||
const Traits& traits=Traits(),
|
||||
bool check_duplicates = false)
|
||||
{
|
||||
using Point_2 = typename Traits::Point_2;
|
||||
using Segment_2 = typename Traits::Segment_2;
|
||||
using I2E = typename Traits::Converter_in;
|
||||
using E2O = typename Traits::Converter_out;
|
||||
using VectorIterator = typename std::vector<Segment_2>::iterator;
|
||||
I2E converter_to_exact=traits.converter_to_exact_object();
|
||||
E2O converter_from_exact=traits.converter_from_exact_object();
|
||||
|
||||
std::vector<Segment_2> convert_input;
|
||||
for(InputIterator it=input_begin; it!=input_end; ++it)
|
||||
convert_input.push_back(Segment_2(converter_to_exact(*it)));
|
||||
std::vector<Segment_2> segs;
|
||||
#ifdef DOUBLE_2D_SNAP_VERBOSE
|
||||
std::cout << "Solved intersections" << std::endl;
|
||||
#endif
|
||||
compute_subcurves(convert_input.begin(), convert_input.end(), std::back_inserter(segs));
|
||||
I2E to_exact=traits.converter_to_exact_object();
|
||||
E2O from_exact=traits.converter_from_exact_object();
|
||||
|
||||
#ifdef DOUBLE_2D_SNAP_VERBOSE
|
||||
std::cout << "Change format to range of points and indexes" << std::endl;
|
||||
#endif
|
||||
std::set<Point_2> unique_point_set;
|
||||
std::map<Point_2, int> point_to_index;
|
||||
std::vector<Point_2> pts;
|
||||
std::vector< std::vector< std::size_t> > polylines;
|
||||
|
||||
// Transform range of the segments in the range of points and polyline of indexes
|
||||
for(VectorIterator it=segs.begin(); it!=segs.end(); ++it)
|
||||
{
|
||||
const Point_2& p1 = it->source();
|
||||
const Point_2& p2 = it->target();
|
||||
if(check_duplicates){
|
||||
std::set<Point_2> unique_point_set;
|
||||
std::map<Point_2, int> point_to_index;
|
||||
|
||||
if (unique_point_set.find(p1) == unique_point_set.end()) {
|
||||
unique_point_set.insert(p1);
|
||||
pts.push_back(p1);
|
||||
point_to_index[p1] = pts.size() - 1;
|
||||
// Transform the polygon in a range of points and polylines of indexes
|
||||
for(const typename Polygon_2::Point_2 &p_: P.vertices())
|
||||
{
|
||||
Point_2 p=to_exact(p_);
|
||||
if (unique_point_set.find(p) == unique_point_set.end()) {
|
||||
unique_point_set.insert(p);
|
||||
pts.push_back(p);
|
||||
point_to_index[p] = pts.size() - 1;
|
||||
}
|
||||
}
|
||||
if (unique_point_set.find(p2) == unique_point_set.end()) {
|
||||
unique_point_set.insert(p2);
|
||||
pts.push_back(p2);
|
||||
point_to_index[p2] = pts.size() - 1;
|
||||
|
||||
for(const typename Polygon_2::Segment_2 &s: P.edges()){
|
||||
Point_2 p1=to_exact(s.source());
|
||||
Point_2 p2=to_exact(s.target());
|
||||
std::size_t index1 = point_to_index[p1];
|
||||
std::size_t index2 = point_to_index[p2];
|
||||
polylines.push_back({index1, index2});
|
||||
}
|
||||
} else {
|
||||
for(const typename Polygon_2::Point_2 &p: P.vertices())
|
||||
pts.push_back(to_exact(p));
|
||||
for(size_t i=0; i<P.size()-1; ++i)
|
||||
polylines.push_back({i, i+1});
|
||||
polylines.push_back({P.size()-1,0});
|
||||
}
|
||||
|
||||
for(VectorIterator it=segs.begin(); it!=segs.end(); ++it)
|
||||
{
|
||||
std::size_t index1 = point_to_index[it->source()];
|
||||
std::size_t index2 = point_to_index[it->target()];
|
||||
polylines.push_back({index1, index2});
|
||||
}
|
||||
|
||||
|
||||
// Main algorithm
|
||||
double_snap_rounding_2_disjoint<Concurrency_tag>(pts, polylines, traits);
|
||||
|
||||
|
|
@ -620,20 +616,14 @@ typename OutputContainer::iterator snap_polygons_2(InputIterator input_begin,
|
|||
#endif
|
||||
|
||||
// Output a range of segments while removing duplicate ones
|
||||
std::set< std::pair<std::size_t,std::size_t> > set_out_segs;
|
||||
output.clear();
|
||||
for(auto &poly: polylines){
|
||||
out.clear();
|
||||
for(auto &poly: polylines)
|
||||
for(std::size_t i=1; i<poly.size(); ++i)
|
||||
set_out_segs.emplace((std::min)(poly[i-1],poly[i]),(std::max)(poly[i-1],poly[i]));
|
||||
}
|
||||
for(auto &pair: set_out_segs){
|
||||
output.emplace_back(converter_from_exact(pts[pair.first]), converter_from_exact(pts[pair.second]));
|
||||
assert(pts[pair.first]!=pts[pair.second]);
|
||||
}
|
||||
|
||||
return output.begin();
|
||||
out.push_back(from_exact(pts[poly[i]]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
} //namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
#define DOUBLE_2D_SNAP_VERBOSE
|
||||
#define BENCH_AND_VERBOSE_FLOAT_SNAP_ROUNDING_2
|
||||
#define COMPARE_WITH_INTEGER_SNAP_ROUNDING_2
|
||||
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
|
|
@ -129,69 +127,47 @@ void test_almost_indentical_segments(CGAL::Random &r, size_t nb_segments, Vector
|
|||
}
|
||||
|
||||
void test_iterative_square_intersection(CGAL::Random &r, size_t nb_iterations){
|
||||
auto add_random_rotated_square=[&](std::vector<Segment_2> &segs){
|
||||
auto random_rotated_square=[&](){
|
||||
double theta=r.get_double(0, CGAL_PI/2);
|
||||
double cos_t = std::cos(theta);
|
||||
double sin_t = std::sin(theta);
|
||||
Point_2 a( cos_t, sin_t);
|
||||
Point_2 b( sin_t,-cos_t);
|
||||
Point_2 c(-cos_t,-sin_t);
|
||||
Point_2 d(-sin_t, cos_t);
|
||||
segs.emplace_back(a,b);
|
||||
segs.emplace_back(b,c);
|
||||
segs.emplace_back(c,d);
|
||||
segs.emplace_back(d,a);
|
||||
#ifdef BENCH_AND_VERBOSE_FLOAT_SNAP_ROUNDING_2
|
||||
std::cout << "Angle: " << theta << std::endl;
|
||||
#endif
|
||||
FT cos_t(std::cos(theta));
|
||||
FT sin_t(std::sin(theta));
|
||||
Polygon_2 P;
|
||||
P.push_back(Point_2( cos_t, sin_t));
|
||||
P.push_back(Point_2(-sin_t, cos_t));
|
||||
P.push_back(Point_2(-cos_t,-sin_t));
|
||||
P.push_back(Point_2( sin_t,-cos_t));
|
||||
return P;
|
||||
};
|
||||
|
||||
std::vector<Segment_2> segs;
|
||||
std::vector<Segment_2> out;
|
||||
std::vector<Curve_2> arr_segs;
|
||||
Polygon_2 scene=random_rotated_square();
|
||||
Polygon_2 snap_scene;
|
||||
Pwh_vec_2 out_intersection;
|
||||
|
||||
CGAL::Real_timer t;
|
||||
for(size_t i=0; i<nb_iterations; ++i){
|
||||
std::cout << "Iterations " << i << std::endl;
|
||||
out.clear();
|
||||
arr_segs.clear();
|
||||
|
||||
for(int j=0; j<5; ++j)
|
||||
add_random_rotated_square(segs);
|
||||
|
||||
test(segs);
|
||||
CGAL::compute_snapped_subcurves_2(segs.begin(), segs.end(), out);
|
||||
assert(!CGAL::do_curves_intersect(out.begin(), out.end()));
|
||||
|
||||
segs.clear();
|
||||
segs.insert(segs.begin(), out.begin(), out.end());
|
||||
out_intersection.clear();
|
||||
CGAL::intersection(random_rotated_square(), scene, std::back_inserter(out_intersection));
|
||||
assert(out_intersection.size()==1 && out_intersection[0].number_of_holes()==0);
|
||||
#ifdef BENCH_AND_VERBOSE_FLOAT_SNAP_ROUNDING_2
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
#endif
|
||||
snap_polygons_2(out_intersection[0].outer_boundary(), snap_scene);
|
||||
// snap_scene=out_intersection[0].outer_boundary();
|
||||
#ifdef BENCH_AND_VERBOSE_FLOAT_SNAP_ROUNDING_2
|
||||
t.stop();
|
||||
std::cout << "Iteration " << i << std::endl;
|
||||
std::cout << "Polygon size: " << out_intersection[0].outer_boundary().size()
|
||||
<< " , Snapped polygon size: " << snap_scene.size() << std::endl;
|
||||
std::cout << "is convex: " << snap_scene.is_convex() << std::endl;
|
||||
std::cout << "Running time: " << t.time() << std::endl;
|
||||
#endif
|
||||
scene=snap_scene;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// void test_iterative_square_intersection(CGAL::Random &r, size_t nb_iterations){
|
||||
// auto random_rotated_square=[&](){
|
||||
// double theta=r.get_double(0, CGAL_PI/2);
|
||||
// double cos_t = std::cos(theta);
|
||||
// double sin_t = std::sin(theta);
|
||||
// Polygon_2 P;
|
||||
// P.push_back( cos_t, sin_t);
|
||||
// P.push_back( sin_t,-cos_t);
|
||||
// P.push_back(-cos_t,-sin_t);
|
||||
// P.push_back(-sin_t, cos_t);
|
||||
// return P;
|
||||
// };
|
||||
|
||||
// Pwh_vec_2 scene, out_intersection;
|
||||
|
||||
// CGAL::intersection(random_rotated_square, random_rotated_square, scene);
|
||||
|
||||
// for(size_t i=0; i<nb_iterations; ++i){
|
||||
// CGAL::intersection(random_rotated_square, random_rotated_square, out_intersection);
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// }
|
||||
|
||||
void test_multi_almost_indentical_segments(CGAL::Random &r, size_t nb_segments){
|
||||
for(double x1=-1; x1<=1; ++x1)
|
||||
for(double y1=-1; y1<=1; ++y1)
|
||||
|
|
@ -222,26 +198,15 @@ void fix_test(){
|
|||
test(segs);
|
||||
}
|
||||
|
||||
void test_box_intersection(){
|
||||
std::vector< Segment_2 > segs;
|
||||
FT e(std::pow(2, -60));
|
||||
segs.emplace_back(Point_2(0, 0), Point_2(1, 1));
|
||||
segs.emplace_back(Point_2(0.5+e, 0.5), Point_2(1, -1));
|
||||
segs.emplace_back(Point_2(0.5-e, 0.5), Point_2(-1, 3));
|
||||
|
||||
test(segs);
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
CGAL::Random rp;
|
||||
CGAL::Random r(argc==1?rp.get_seed():std::stoi(argv[1]));
|
||||
std::cout << "random seed = " << r.get_seed() << std::endl;
|
||||
std::cout << std::setprecision(17);
|
||||
test_box_intersection();
|
||||
fix_test();
|
||||
// test_fully_random(r,1000);
|
||||
// test_multi_almost_indentical_segments(r,100);
|
||||
// test_iterative_square_intersection(r,500);
|
||||
test_iterative_square_intersection(r,2000);
|
||||
return(0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue