// case with four segments cutting the one segment in four parts in // container the fitting line must be the same void test_3() { std::cout<<"Test 3"<<std::endl; std::list<Segment_2> segments; segments.push_back(Segment_2(Point_2(2.0,2.0),Point_2(1.75,1.75))); segments.push_back(Segment_2(Point_2(1.0,1.0),Point_2(1.25,1.25))); segments.push_back(Segment_2(Point_2(1.5,1.5),Point_2(1.25,1.25))); segments.push_back(Segment_2(Point_2(1.5,1.5),Point_2(1.75,1.75))); // fit a line // call all versions of the function std::cout << "fit 2D line..."; Line_2 line; Point_2 centroid; FT quality; quality = linear_least_squares_fitting_2(segments.begin(),segments.end(),line,CGAL::Dimension_tag<1>()); quality = linear_least_squares_fitting_2(segments.begin(),segments.end(),line,centroid,CGAL::Dimension_tag<1>()); std::cout << "done (quality: " << quality << ")" << std::endl; if(!(std::abs(-1.0*line.a()/line.b() - 1) <= THRESHOLD && std::abs(line.c()/line.b()) <= THRESHOLD && 1 - quality <= THRESHOLD)) { std::cout << "failure" << std::endl; std::exit(1); // failure } }
// case with a point set on a segment vs the segment // the fitting line must be the same segment void test_5(const unsigned int nb_points) { std::cout<<"Test 5"<<std::endl; // create points on a horizontal segment Point_2 p(2.0,0.0); Point_2 q(5.0,5.0); std::cout << "generate " << nb_points << " 2D points on a horizontal line..."; std::list<Point_2> points; points_on_segment_2(p,q,100,std::back_inserter(points)); std::cout << "done " << std::endl; // fit a line std::cout << "fit 2D line to points..."; Line_2 line; Point_2 centroid; // call all versions of the function FT quality; quality = linear_least_squares_fitting_2(points.begin(),points.end(),line,CGAL::Dimension_tag<0>()); quality = linear_least_squares_fitting_2(points.begin(),points.end(),line,centroid,CGAL::Dimension_tag<0>()); std::cout << "done (quality: " << quality << ")" <<" line: "<<line<< std::endl; std::list<Segment_2> segments; segments.push_back(Segment_2(p,q)); // fit a line // call all versions of the function std::cout << "fit 2D line to segment..."; Line_2 line1; Point_2 centroid1; FT quality1; quality1 = linear_least_squares_fitting_2(segments.begin(),segments.end(),line1,CGAL::Dimension_tag<1>()); quality1 = linear_least_squares_fitting_2(segments.begin(),segments.end(),line1,centroid1,CGAL::Dimension_tag<1>()); std::cout << "done (quality: " << quality1 << ")" <<" line: "<<line1<< std::endl; if(!(std::abs(-1.0*line.a()/line.b() - -1.0*line1.a()/line1.b()) <= THRESHOLD && std::abs(line.c()/line.b() - line1.c()/line1.b()) <= THRESHOLD && std::abs(quality1 - quality) <= THRESHOLD)) { std::cout << "failure" << std::endl; std::exit(1); // failure } }
// case with one rectangle in container vs it split into four triangles // the fitting line must be the same. void test_2() { std::cout<<"Test 2"<<std::endl; std::list<Iso_rectangle_2> iso_rectangles; iso_rectangles.push_back(Iso_rectangle_2(Point_2(1.6,15.2),Point_2(11.6,19.2))); // fit a line // call all versions of the function std::cout << "fit 2D line to bigger rectangle..."; Line_2 line; Point_2 centroid; FT quality; quality = linear_least_squares_fitting_2(iso_rectangles.begin(),iso_rectangles.end(),line,CGAL::Dimension_tag<2>()); quality = linear_least_squares_fitting_2(iso_rectangles.begin(),iso_rectangles.end(),line,centroid,CGAL::Dimension_tag<2>()); std::cout << "done (quality: " << quality << ") Line: " << line<<" centroid: "<<centroid<<std::endl; std::list<Triangle_2> triangles1; triangles1.push_back(Triangle_2(Point_2(1.6,15.2),Point_2(1.6,19.2),Point_2(6.6,17.2))); triangles1.push_back(Triangle_2(Point_2(11.6,19.2),Point_2(11.6,15.2),Point_2(6.6,17.2))); triangles1.push_back(Triangle_2(Point_2(1.6,19.2),Point_2(11.6,19.2),Point_2(6.6,17.2))); triangles1.push_back(Triangle_2(Point_2(1.6,15.2),Point_2(11.6,15.2),Point_2(6.6,17.2))); // fit a line // call all versions of the function std::cout << "fit 2D line to four small triangles..."; Line_2 line1; Point_2 centroid1; FT quality1; quality1 = linear_least_squares_fitting_2(triangles1.begin(),triangles1.end(),line1,CGAL::Dimension_tag<2>()); quality1 = linear_least_squares_fitting_2(triangles1.begin(),triangles1.end(),line1,centroid1,CGAL::Dimension_tag<2>()); std::cout << "done (quality: " << quality1 << ") Line: " << line1<<" centroid: "<<centroid1<<std::endl; if(!(std::abs(-1.0*line.a()/line.b() - -1.0*line1.a()/line1.b()) <= THRESHOLD && std::abs(line.c()/line.b() - line1.c()/line1.b()) <= THRESHOLD && std::abs(quality1 - quality) <= THRESHOLD)) { std::cout << "failure" << std::endl; std::exit(1); // failure } }
// case with a segments in container against just the two end points // the fitting line must be the same void test_4() { std::cout<<"Test 4"<<std::endl; Point_2 p = Point_2(1.0,0.0); Point_2 q = Point_2(0.0,1.0); std::list<Segment_2> segments; segments.push_back(Segment_2(p,q)); // fit a line // call all versions of the function std::cout << "fit 2D line to segment..."; Line_2 line; Point_2 centroid; FT quality; quality = linear_least_squares_fitting_2(segments.begin(),segments.end(),line,CGAL::Dimension_tag<1>()); quality = linear_least_squares_fitting_2(segments.begin(),segments.end(),line,centroid,CGAL::Dimension_tag<1>()); std::cout << "done (quality: " << quality << ")" <<" line: "<<line<< std::endl; std::list<Point_2> points; points.push_back(p); points.push_back(q); // fit a line // call all versions of the function std::cout << "fit 2D line to end points..."; Line_2 line1; Point_2 centroid1; FT quality1; quality1 = linear_least_squares_fitting_2(points.begin(),points.end(),line1,CGAL::Dimension_tag<0>()); quality1 = linear_least_squares_fitting_2(points.begin(),points.end(),line1,centroid1,CGAL::Dimension_tag<0>()); std::cout << "done (quality: " << quality1 << ")" <<" line: "<<line1<<std::endl; if(!(std::abs(-1.0*line.a()/line.b() - -1.0*line1.a()/line1.b()) <= THRESHOLD && std::abs(line.c()/line.b() - line1.c()/line1.b()) <= THRESHOLD && std::abs(quality1 - quality) <= THRESHOLD)) { std::cout << "failure" << std::endl; std::exit(1); // failure } }
std::vector<uv> gridfit2D(const std::vector<uv>& input){ // 1. gather points for lines std::vector<std::vector<Point> > h_points(CB_HEIGHT); std::vector<std::vector<Point> > v_points(CB_WIDTH); for(unsigned cp_id = 0; cp_id < CB_WIDTH*CB_HEIGHT; ++cp_id){ const unsigned h_id = cp_id / CB_WIDTH; h_points[h_id].push_back(Point(input[cp_id].u,input[cp_id].v)); const unsigned v_id = cp_id % CB_WIDTH; v_points[v_id].push_back(Point(input[cp_id].u,input[cp_id].v)); } std::vector<Line > h_lines; for(const auto& points: h_points){ Line l; const float fitting_quality = linear_least_squares_fitting_2(points.begin(), points.end(),l,CGAL::Dimension_tag<0>()); h_lines.push_back(l); } std::vector<Line > v_lines; for(const auto& points: v_points){ Line l; const float fitting_quality = linear_least_squares_fitting_2(points.begin(), points.end(),l,CGAL::Dimension_tag<0>()); v_lines.push_back(l); } std::vector<uv> output(CB_WIDTH*CB_HEIGHT); for(unsigned cp_id = 0; cp_id < CB_WIDTH*CB_HEIGHT; ++cp_id){ const unsigned h_id = cp_id / CB_WIDTH; const unsigned v_id = cp_id % CB_WIDTH; CGAL::cpp11::result_of<Intersect(Line, Line)>::type result = intersection(h_lines[h_id], v_lines[v_id]); uv cp = input[cp_id]; if(result){ if (const Segment* s = boost::get<Segment>(&*result)) { //std::cout << *s << std::endl; } else { const Point* p = boost::get<Point>(&*result); std::cout << "INFO: fitted crossing point id " << cp_id << " to point: " << *p << std::endl; // This is what we want cp.u = p->x(); cp.v = p->y(); } } output[cp_id] = cp; } return output; }
void pcaIpelet::protected_run(int fn) { if (fn==1) { show_help(); return; } std::list<Point_2> pt_list; std::list<Circle_2> cir_list; std::list<Polygon_2> poly_list; std::list<Kernel::Triangle_2> tri_list; std::list<Segment_2> sg_list; Iso_rectangle_2 bbox= read_active_objects( CGAL::dispatch_or_drop_output<Point_2,Polygon_2,Circle_2,Segment_2>( std::back_inserter(pt_list), std::back_inserter(poly_list), std::back_inserter(cir_list), std::back_inserter(sg_list) ) ); for (std::list<Polygon_2>::iterator it=poly_list.begin();it!=poly_list.end();++it) if (it->size()==3){ tri_list.push_back(Kernel::Triangle_2(*(it->vertices_begin()), *boost::next(it->vertices_begin()), *boost::next(it->vertices_begin(),2) )); } else{ print_error_message("This implementation is limited to triangles"); return; } int s=0; if (!pt_list.empty()) s=1; if (!cir_list.empty()) s+=2; if (!tri_list.empty()) s+=4; if (!sg_list.empty()) s+=8; if (s==0) { print_error_message("Nothing is selected"); return; } Kernel::Line_2 line; Kernel::Point_2 centroid; switch (s){ case 1://points linear_least_squares_fitting_2(pt_list.begin(),pt_list.end(),line,centroid,CGAL::Dimension_tag<0>()); break; case 2://circles linear_least_squares_fitting_2(cir_list.begin(),cir_list.end(),line,centroid,CGAL::Dimension_tag<2>()); break; case 4://triangles linear_least_squares_fitting_2(tri_list.begin(),tri_list.end(),line,centroid,CGAL::Dimension_tag<2>()); break; case 8://segments linear_least_squares_fitting_2(sg_list.begin(),sg_list.end(),line,centroid,CGAL::Dimension_tag<1>()); break; default: print_error_message("Please select a set of points or segments or triangles or circles"); return; } CGAL::Object obj_cgal = CGAL::intersection(line,bbox); Segment_2 seg; if (CGAL::assign(seg, obj_cgal)) draw_in_ipe(seg); }