VectorPolygon clip_onPlane(const VectorPolygon polygon, const vigra::Rect2D r, const clipSide side) { if(polygon.size()<3) { return polygon; }; FDiff2D s=polygon[polygon.size()-1]; FDiff2D p; VectorPolygon newPolygon; for(unsigned int i=0;i<polygon.size();i++) { p=polygon[i]; if(clip_isSide(p,r,side)) { // point p is "inside" if(!clip_isSide(s,r,side)) // and point s is "outside" newPolygon.push_back(clip_getIntersection(p,s,r,side)); newPolygon.push_back(p); } else { //point p is "outside" if(clip_isSide(s,r,side)) //ans point s is "inside" newPolygon.push_back(clip_getIntersection(s,p,r,side)); }; s=p; }; return newPolygon; };
void test_access_functions(VectorPolygon& p) { cout << "p.size() = " << p.size() << endl; cout << "p.is_empty() = " << (p.is_empty() ? "true" : "false") << endl; // test random access methods for (std::size_t i=0; i<p.size(); i++) { cout << "vertex " << i << " = " << p.vertex(i) << endl; cout << "edge " << i << " = " << p.edge(i) << endl; } typedef CGAL::Polygon_2<K, vector<Point> >::Edge_const_iterator EI; EI edges_begin = p.edges_begin(); EI edges_end = p.edges_end(); assert(edges_begin < edges_end); }
/** adds an arc with given radius at the end of the polygon, the point is not added to the arc @param poly polygon to which the arc should added @param s point to which the arc should go @param center center of arc @param radius radius of arc @param clockwise true, if arc should go clockwise; else it goes anti-clockwise */ void generateArc(VectorPolygon& poly, const FDiff2D s, const FDiff2D center, const double radius, const bool clockwise) { if(poly.size()==0) { return; }; FDiff2D p=poly[poly.size()-1]; double maxDistance=5.0; if(p.squareDistance(s)<maxDistance*maxDistance) { return; }; double angle=atan2(p.y-center.y,p.x-center.x); double final_angle=atan2(s.y-center.y,s.x-center.x); //step 1 degree or less, so that max distance between 2 points is smaller than maxDistance double step=std::min<double>(PI/180,atan2(maxDistance,radius)); if(!clockwise) { while(final_angle<angle) { final_angle+=2*PI; }; angle+=step; while(angle<final_angle) { poly.push_back(FDiff2D(cos(angle)*radius+center.x,sin(angle)*radius+center.y)); angle+=step; }; } else { while(final_angle>angle) { final_angle-=2*PI; }; angle-=step; while(angle>final_angle) { poly.push_back(FDiff2D(cos(angle)*radius+center.x,sin(angle)*radius+center.y)); angle-=step; }; }; };
bool MaskPolygon::clipPolygon(const FDiff2D center,const double radius) { if(radius<=0 || m_polygon.size()<3) { return false; }; FDiff2D s=m_polygon[m_polygon.size()-1]; bool s_inside=clip_insideCircle(s,center,radius); FDiff2D p; VectorPolygon newPolygon; bool needsFinalArc=false; double angleCovered=0; double angleCoveredOffset=0; for(unsigned int i=0;i<m_polygon.size();i++) { p=m_polygon[i]; bool p_inside=clip_insideCircle(p,center,radius); if(p_inside) { if(s_inside) { //both points inside newPolygon.push_back(p); } else { //line crosses circles from outside std::vector<FDiff2D> points=clip_getIntersectionCircle(p,s,center,radius); DEBUG_ASSERT(points.size()==1); angleCovered+=angle_between(s-center,points[0]-center); if(newPolygon.size()==0) { needsFinalArc=true; angleCoveredOffset=angleCovered; } else { generateArc(newPolygon,points[0],center,radius,angleCovered<0); }; newPolygon.push_back(points[0]); newPolygon.push_back(p); }; } else { if(!s_inside) { //both points outside of circle std::vector<FDiff2D> points=clip_getIntersectionCircle(s,p,center,radius); //intersection can only be zero points or 2 points if(points.size()>1) { angleCovered+=angle_between(s-center,points[0]-center); if(newPolygon.size()==0) { needsFinalArc=true; angleCoveredOffset=angleCovered; } else { generateArc(newPolygon,points[0],center,radius,angleCovered<0); }; newPolygon.push_back(points[0]); newPolygon.push_back(points[1]); angleCovered=angle_between(points[1]-center,p-center); } else { angleCovered+=angle_between(s-center,p-center); }; } else { //line segment intersects circle from inside std::vector<FDiff2D> points=clip_getIntersectionCircle(s,p,center,radius); angleCovered=0; DEBUG_ASSERT(points.size()==1); newPolygon.push_back(points[0]); }; }; s=p; s_inside=p_inside; }; if(needsFinalArc && newPolygon.size()>1) { generateArc(newPolygon,newPolygon[0],center,radius,(angleCovered+angleCoveredOffset)<0); }; m_polygon=newPolygon; return (m_polygon.size()>2); };