int Spline::Get_new_hnode(Path* path, double r, double f) { //this routine calculates new points laying on the "skeleton line" //of the path line by intersecting perpendicular lines to the initial spline //with the path line segments //calculate the perpendicular line defined by a point p on the spline //and the slope dy/dx at the parameter r double dx,dy; CamPoint p; Get_point(&p, r); Get_derivative(r, &dx, &dy); //now intersect the path with the line defined by p and (dy,-dx) //(the line pependicular to the b-spline) by calculating the //distance between a pixel and the line and //convert the line into a form ax+by+c=0 where -m*x - y-m*x_p +y_p = 0 double a = -dx/dy; double b = -1; double c = p.y - a*p.x; int i_p1,i_p2; bool found1=FALSE, found2=FALSE; double nenner = sqrt(a*a+b*b); //tolerance is the maximal distance between a point of a line and a point of a //path segment so that the line is defined to intersect the boundary of the path //segment. sqrt(2)*0.009/f/2.0 is half of the diagonal length of a normalized pixel double tolerance=sqrt(2)*0.009/f/2.0; //get the relevant segment number double j_p; modf(r,&j_p); double d; for(int i=0; i< path->path_seg[(int)j_p].p_nr; i++) { d= fabs(a*path->path_seg[(int)j_p].hpixel[i].x + b*path->path_seg[(int)j_p].hpixel[i].y + c) / nenner; if(d < tolerance && found1) { i_p2 = i; found2=TRUE; break; } if(d < tolerance && found1 == FALSE) { i_p1 = i; found1=TRUE; //go two pixel further because a wrong intersection on the same segment line might be found i+=2; } } if(found1 && found2 && i_p1 != i_p2) { node[m].x = (path->path_seg[(int)j_p].hpixel[i_p1].x + path->path_seg[(int)j_p].hpixel[i_p2].x)/2.0; node[m].y = (path->path_seg[(int)j_p].hpixel[i_p1].y + path->path_seg[(int)j_p].hpixel[i_p2].y)/2.0; parameter[m]=r; m++; if(m>=2500) return 2; } return 0; }
int Spline::Line_intersect(double a, double b, double c, CamPoint *hp, double *r_l, double r_u) { //if a solution (intersection is found) TRUE is returned otherwise FALSE //************************************************************************************* //***************************Interval sectioning*************************************** // *r_l is the lower limit and r_u is the upper limit of the intersection // parameter window //the routine returns //0 if a regular solution was found //1 if a solution with a critical intersection angle was found //3 if no or a wrong solution was found int i=0,solution=1; const int max_iter=100; //the maximal number of iterations double aa=*r_l; double bb= r_u; double cc; double res_a,res_b,res_c=1; CamPoint p; const double angle_tol=0;//3.14159/25 Get_point(&p, *r_l); res_a=a*p.x + b*p.y + c; Get_point(&p, r_u); res_b=a*p.x + b*p.y + c; if(res_a <0 && res_b>0) { while(fabs(res_c) > 0.00001) { cc=(aa+bb)/2.0; Get_point(&p, cc); res_c=a*p.x + b*p.y + c; if(res_c<0) aa=cc; else bb=cc; if(++i > max_iter) //no solution found { hp->x=-1; return 3; } } //check solution if(*r_l == cc) { hp->x=-1; //wrong solution return 3; } else { *r_l=cc; //get the intersection angle at the parameter *r_l //-first calculate dy/dx of the spline //angle of the epiline double dx=Get_x_derivative(*r_l); double dy=Get_y_derivative(*r_l); double m_spline=dy/dx; double m_epi =-a/b; double gamma=atan(fabs((m_spline-m_epi)/(1+m_spline+m_epi))); if(gamma>angle_tol) //if the intersection angle is large enough: regular solution found { hp->x=p.x; hp->y=p.y; hp->w=1.0; return 0; } else { return 1; } } } else if(res_a > 0 && res_b < 0) //change { res_c=res_a; res_a=res_b; res_b=res_c; res_c=1; aa= r_u; bb=*r_l; while(fabs(res_c) > 0.00001) { cc=(aa+bb)/2.0; Get_point(&p, cc); res_c=a*p.x + b*p.y + c; if(res_c<0) aa=cc; else bb=cc; if(++i > max_iter) //no solution found { hp->x=-1; return 3; } } //check solution if(*r_l == cc) { //wrong solution hp->x=-1; return 3; } else { *r_l=cc; //get the intersection angle at the parameter *r_l //-first calculate dy/dx of the spline //angle of the epiline double dx=Get_x_derivative(*r_l); double dy=Get_y_derivative(*r_l); double m_spline=dy/dx; double m_epi =-a/b; double gamma=atan(fabs((m_spline-m_epi)/(1+m_spline+m_epi))); if(gamma>angle_tol) //if the intersection angle is large enough: regular solution found { hp->x=p.x; hp->y=p.y; hp->w=1.0; return 0; } else { return 1; } } } else //there is no or more than one intersection-divide the domain and repeat search { hp->x=-1; return 3; } return 0; }
void Polyhedron_demo_convex_hull_plugin::on_actionConvexHull_triggered() { const Scene_interface::Item_id index = scene->mainSelectionIndex(); Scene_polyhedron_item* poly_item = qobject_cast<Scene_polyhedron_item*>(scene->item(index)); Scene_points_with_normal_item* pts_item = qobject_cast<Scene_points_with_normal_item*>(scene->item(index)); Scene_polylines_item* lines_item = qobject_cast<Scene_polylines_item*>(scene->item(index)); Scene_polyhedron_selection_item* selection_item = qobject_cast<Scene_polyhedron_selection_item*>(scene->item(index)); if(poly_item || pts_item || lines_item || selection_item) { // wait cursor QApplication::setOverrideCursor(Qt::WaitCursor); QTime time; time.start(); std::cout << "Convex hull..."; // add convex hull as new polyhedron Polyhedron *pConvex_hull = new Polyhedron; if(selection_item) { CGAL::convex_hull_3( boost::make_transform_iterator(selection_item->selected_vertices.begin(), Get_point()), boost::make_transform_iterator(selection_item->selected_vertices.end(), Get_point()), *pConvex_hull); } else if ( poly_item ){ Polyhedron* pMesh = poly_item->polyhedron(); CGAL::convex_hull_3(pMesh->points_begin(),pMesh->points_end(),*pConvex_hull); } else{ if (pts_item) CGAL::convex_hull_3(pts_item->point_set()->begin(),pts_item->point_set()->end(),*pConvex_hull); else{ std::size_t nb_points=0; for(std::list<std::vector<Kernel::Point_3> >::const_iterator it = lines_item->polylines.begin(); it != lines_item->polylines.end(); ++it) nb_points+=it->size(); std::vector<Kernel::Point_3> all_points; all_points.reserve( nb_points ); for(std::list<std::vector<Kernel::Point_3> >::const_iterator it = lines_item->polylines.begin(); it != lines_item->polylines.end(); ++it) std::copy(it->begin(), it->end(),std::back_inserter( all_points ) ); CGAL::convex_hull_3(all_points.begin(),all_points.end(),*pConvex_hull); } } std::cout << "ok (" << time.elapsed() << " ms)" << std::endl; Scene_polyhedron_item* new_item = new Scene_polyhedron_item(pConvex_hull); new_item->setName(tr("%1 (convex hull)").arg(scene->item(index)->name())); new_item->setColor(Qt::magenta); new_item->setRenderingMode(FlatPlusEdges); scene->addItem(new_item); // default cursor QApplication::restoreOverrideCursor(); } }