void convex_hull(polygon in, polygon& hull){ hull.clear(); if(in.size() < 3){ hull = in; return; } int pos = 0; for(int i = 1; i < in.size(); i++) if(in[i] < in[pos]) pos = i; swap(in[0], in[pos]); refer = in[0]; sort(in.begin() + 1, in.end(), cmp_angle); in.resize(unique(in.begin(), in.end()) - in.begin()); hull.push_back(in[0]); hull.push_back(in[1]); in.push_back(in[0]); //isto evita pontos colineares no final do poligono for(int i = 2; i < in.size(); ){ if(hull.size() > 2 && side_sign(hull[hull.size() - 2], hull[hull.size() - 1], in[i]) <= 0){ hull.pop_back(); } else hull.push_back(in[i++]); } //tira a duplicata hull.pop_back(); }
//testa se o ponto esta dentro de um poligono (nao necessariamente convexo) bool inside_poly(pt p, polygon poly){ poly.push_back(poly[0]); for(int i = 0; i < poly.size()-1; i++) if(point_and_seg(poly[i], poly[i+1], p)) return true; //na borda for(int i = 0; i < poly.size()-1; i++) poly[i] = poly[i] - p; p = pt(0, 0); double theta, y; while(true){ theta = (double)rand()/10000.0; bool inter = false; //evita que um ponto fique no eixo x for(int i = 0; i < poly.size()-1; i++){ poly[i] = rotate(poly[i], theta); if( !cmp(poly[i].x) ) inter = true; } if( !inter ){ poly[poly.size()-1] = poly[0]; //testa as possiveis intersecoes for(int i = 0; i < poly.size()-1; i++){ if( cmp( poly[i].x * poly[i+1].x ) < 0 ){ y = poly[i+1].y - poly[i+1].x * (poly[i].y - poly[i+1].y) / (poly[i].x - poly[i+1].x); if( cmp(y) > 0 ) inter = !inter; //se interecao valida } } return inter; //testa a paridade da semi-reta vertical partindo de p } } return true; }
// Returns a list of points on the convex hull in counter-clockwise order. // NOTE: the last point in the returned list is the same as the first one. void convex_hull_2(polygon P, polygon& hull) { hull.clear(); // Sort points lexicographically sort(P.begin(), P.end()); P.resize(unique(P.begin(), P.end()) - P.begin()); // Build lower hull for (int i = 0; i < P.size(); i ++) { while (hull.size() >= 2 && side_sign(hull[hull.size() - 2], hull[hull.size() - 1], P[i]) <= 0) hull.pop_back(); hull.push_back(P[i]); }; // Build upper hull for (int i = P.size()-2, t = hull.size() + 1; i >= 0; i --) { while (hull.size() >= t && side_sign(hull[hull.size()-2], hull[hull.size()-1], P[i]) <= 0) hull.pop_back(); hull.push_back(P[i]); }; }
void rotatingCalipers(polygon pg) { pg.push_back(pg.front()); for (int i = 0, j = 1, n = pg.size() - 1; i < n; i++) { while (cross(pg[i + 1] - pg[i], pg[j + 1] - pg[j]) > 0) j = (j + 1) % n; double dist1 = pg[i].distTo(pg[j - 1]); double dist2 = pg[i].distTo(pg[j]); double dist3 = pg[i].distTo(pg[j + 1]); int r1 = j + 1, r2 = j + 2; cout << (j - 1) << '=' << dist1 << ' ' << j << '=' << dist2 << ' ' << (j + 1) << '=' << dist3 << '\n'; if (r1 >= n) r1 = 1; if (r2 >= n) r2 = 1; if (dist2 > dist3) cout << r1 << '\n'; else if (dist3 > dist2) cout << r2 << '\n'; else cout << min(r1, r2) << '\n'; } }