polygon convex_intersect(const polygon &P, const polygon &Q) { const int n = P.size(), m = Q.size(); int a = 0, b = 0, aa = 0, ba = 0; enum { Pin, Qin, Unknown } in = Unknown; polygon R; do { int a1 = (a+n-1) % n, b1 = (b+m-1) % m; number C = cross(P[a] - P[a1], Q[b] - Q[b1]); number A = cross(P[a1] - Q[b], P[a] - Q[b]); number B = cross(Q[b1] - P[a], Q[b] - P[a]); point r; if (intersect_1pt(P[a1], P[a], Q[b1], Q[b], r)) { if (in == Unknown) aa = ba = 0; R.push_back( r ); in = B > number(0) ? Pin : A > number(0) ? Qin : in; } if (C == number(0) && B == number(0) && A == number(0)) { if (in == Pin) { b = (b + 1) % m; ++ba; } else { a = (a + 1) % m; ++aa; } } else if (C >= number(0)) { if (A > number(0)) { if (in == Pin) R.push_back(P[a]); a = (a+1)%n; ++aa; } else { if (in == Qin) R.push_back(Q[b]); b = (b+1)%m; ++ba; } } else { if (B > number(0)) { if (in == Qin) R.push_back(Q[b]); b = (b+1)%m; ++ba; } else { if (in == Pin) R.push_back(P[a]); a = (a+1)%n; ++aa; } } } while ( (aa < n || ba < m) && aa < 2*n && ba < 2*m ); if (in == Unknown) { if (contains(Q, P[0])) return P; if (contains(P, Q[0])) return Q; } return R; }
double perimeter(polygon p){ double per = 0.0; for(int i = 0; i < p.size(); i++){ per += dist(p[i], p[(i+1)%p.size()]); } return per; }
double area(polygon& poly){ double ret = 0.0; for(int i = 0; i < poly.size(); i++){ ret += trap(poly[i], poly[(i+1)%poly.size()]); } return fabs(ret); }
//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; }
//testa se o ponto esta no poligono convexo bool inside_convex_poly(pt p, polygon& poly){ int left = 0, right = 0, side; for(int i = 0; i < poly.size(); i++){ side = side_sign(p, poly[i], poly[(i+1)%poly.size()]); if(side < 0) right++; if(side > 0) left++; } return !(left && right); }
//Determina se o poligono simples eh convexo bool is_convex(polygon& p){ int left = 0, right = 0, side; for(int i = 0; i < p.size(); i++){ side = side_sign(p[i], p[(i+1)%p.size()], p[(i+2)%p.size()]); if(side < 0) right++; if(side > 0) left++; } return !(left && right); }
double dist(const polygon &a, const polygon &b) { double ret = 1e100; for (int i = 0; i < (int)a.size() - 1; ++ i) for (int j = 0; j < (int)b.size() - 1; ++ j) { ret = min(ret, dist(a[i], b[j], b[j + 1])); ret = min(ret, dist(b[j], a[i], a[i + 1])); } return ret; }
bool positiveArea(polygon p) { for (int i = 0; i < p.size(); ++i) { for (int j = i + 1; j < p.size(); ++j) { for (int k = j + 1; k < p.size(); ++k) { if (collineal(p[0], p[1], p[2])) return false; } } } return true; }
bool polygonintersect(const polygon &a, const polygon &b) { for (int i = 0; i < (int)a.size() - 1; ++ i) if (inside(a[i], b)) return true; for (int i = 0; i < (int)b.size() - 1; ++ i) if (inside(b[i], a)) return true; for (int i = 0; i < (int)a.size() - 1; ++ i) for (int j = 0; j < (int)b.size() - 1; ++ j) if (intersect(a[i], a[i + 1], b[j], b[j + 1])) return true; return false; }
// 두 다각형이 서로 닿거나 겹치는지 여부를 반환한다. // 한 점이라도 겹친다면 true 를 반환한다. bool polygonIntersects(const polygon& p, const polygon& q) { int n = p.size(), m = q.size(); // 우선 한 다각형이 다른 다각형에 포함되어 있는 경우를 확인하자 if(isInside(p[0], q) || isInside(q[0], p)) return true; // 이외의 경우, 두 다각형이 서로 겹친다면 서로 닿는 두 변이 반드시 존재한다 for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) if(segmentIntersects(p[i], p[(i+1)%n], q[j], q[(j+1)%m])) return true; return false; }
pt centroid(polygon p){ double a = area(p); double xc = 0.0, yc = 0.0; for(int i = 0; i < p.size(); i++){ int next = (i+1)%p.size(); xc += (p[i].x + p[next].x)*(p[i].x*p[next].y - p[next].x*p[i].y); yc += (p[i].y + p[next].y)*(p[i].x*p[next].y - p[next].x*p[i].y); } return pt(xc/(6.0*a), yc/(6.0*a)); }
int isPointInPolygon(point p, polygon &pg) { bool in = false; for (int i = 0; i < pg.size(); i++) { point a = pg[i] - p, b = pg[(i + 1) % pg.size()] - p; if (abs(cross(a, b)) < EPSILON && dot(a, b) < EPSILON) return ON; if (a.y > b.y) swap(a, b); if (a.y < EPSILON && EPSILON < b.y && cross(a, b) > EPSILON) in = !in; } return in ? IN : OUT; }
inline void draw(const polygon<T,2>& polygon) { if (polygon.size() < 3) return; std::size_t j = polygon.size() - 1; for (std::size_t i = 0; i < polygon.size(); ++i) { draw_segment(polygon[i],polygon[j]); j = i; } }
bool isugly(const polygon <float> & pol) { if (pol.size() < 3) return true; //Add other ugly conditions return false; }
int in_poly(point p, polygon& T) { double a = 0; int N = T.size(); for (int i = 0; i < N; i++) { if (between(T[i], p, T[(i+1) % N])) return -1; a += angle(T[i], p, T[(i+1) % N]); } return cmp(a) != 0; }
/** * @brief Add a polygon to the mesh. * @param p */ void Mesh::add_polygon( polygon& p ) { polygons.push_back( p ); if ( p.size() == 3 ) { tris.push_back( p.at(0) ); tris.push_back( p.at(1) ); tris.push_back( p.at(2) ); } if ( p.size() == 4 ) { quads.push_back( p.at(0) ); quads.push_back( p.at(1) ); quads.push_back( p.at(2) ); quads.push_back( p.at(3) ); } }
bool inside(const point &a, const polygon &p) { double cnt = 0; for (int i = 0; i < (int)p.size() - 1; ++ i) { point x = p[i] - a, y = p[i + 1] - a; if (abs(x) == 0 || abs(y) == 0) return true; cnt += asin(cross(x, y) / abs(x) / abs(y)); } return fabs(cnt) >= 2 * pi - eps; }
double getArea(polygon &pg) { double area = 0.0; int n = pg.size(); if (n < 3) return area; for (int i = 0, j = 1; i < n; i++, j = (i + 1) % n) area += (pg[i].x * pg[j].y - pg[j].x * pg[i].y); return fabs(area / 2.0); }
int contains(const polygon& P, const point& p) { bool in = false; for (int i = 0; i < P.size(); ++i) { point a = curr(P,i) - p, b = next(P,i) - p; if (imag(a) > imag(b)) swap(a, b); if (imag(a) <= number(0) && number(0) < imag(b)) if (cross(a, b) < number(0)) in = !in; if (cross(a, b) == number(0) && dot(a, b) <= number(0)) return ON; } return in ? IN : OUT; }
int contains(const polygon& G, const P& p) { bool in = false; for (int i = 0; i < G.size(); ++i) { P a = curr(G,i) - p, b = next(G,i) - p; if (imag(a) > imag(b)) swap(a, b); if (imag(a) <= 0 && 0 < imag(b)) if (cross(a, b) < 0) in = !in; if (cross(a, b) == 0 && dot(a, b) <= 0) return ON; } return in ? IN : OUT; }
point center(const polygon& poly) { double x = 0.0; double y = 0.0; for (auto& p : poly) { x += p.x / poly.size(); y += p.y / poly.size(); } return { x, y }; }
//Corta o poligono pela reta ab //pol1 - poligono do lado esquerdo //pol2 - poligono do lado direito void cut_polygon(polygon pol, pt a, pt b, polygon& pol1, polygon& pol2){ polygon pp, pn; pt p1, p2, r; for(int i = 0; i < pol.size(); i++){ p1 = pol[i]; p2 = pol[(i+1)%pol.size()]; int side = side_sign(a, b, p1); if(side >= 0) pp.push_back(p1); if(side <= 0) pn.push_back(p1); if(intersect(a, b, p1, p2, r) && (r == pt(INF, INF))){ if(point_and_seg(p1, p2, r)){ pp.push_back(r); pn.push_back(r); } } if(pp.size() > 2) convex_hull(pp, pol1); if(pn.size() > 2) convex_hull(pn, pol2); } }
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(); }
polygon poly_intersect(polygon &P, polygon &Q){ int m = Q.size(), n = P.size(); int a = 0, b = 0, aa = 0, ba = 0, inflag = 0; polygon R; while( (aa < n || ba < m) && aa < 2*n && ba < 2*m){ Point p1 = P[a], p2 = P[(a+1) % n], q1 = Q[b], q2 = Q[(b+1) % m]; Point A = p2 - p1, B = q2 - q1; int cross = cmp(A ^ B), ha = turn(p2, q2, p1), hb = turn(q2, p2, q1); if(cross == 0 && turn(p1, q1, p2) == 0 && cmp(A * B) < 0){ if(between(p1, q1, p2)) R.push_back(q1); if(between(p1, q2, p2)) R.push_back(q2); if(between(q1, p1, q2)) R.push_back(p1); if(between(q1, p2, q2)) R.push_back(p2); if(R.size() < 2) return polygon(); inflag = 1; break; }else if(cross != 0 && seg_intersect(p1, p2, q1, q2)) { if(inflag == 0) aa = ba = 0; R.push_back(intersection(p1, p2, q1, q2)); inflag = (hb > 0) ? 1 : -1; } if(cross == 0 && hb < 0 && ha < 0) return R; bool t = cross == 0 && hb == 0 && ha == 0; if(t ? (inflag == 1) : (cross >= 0) ? (ha <= 0) : (hb > 0)){ if(inflag == -1) R.push_back(q2); ba++; b++; b %= m; }else{ if(inflag == 1) R.push_back(p2); aa++; a++; a %= n; } } if(inflag == 0){ if (in_polygon(P[0], Q)) return P; if (in_polygon(Q[0], P)) return Q; } R.erase(unique(R.begin(), R.end()), R.end()); if(R.size() > 1 && R.front() == R.back()) R.pop_back(); return R; }
point getCentroid1(polygon &pg) { double areaOfPolygon = 0, areaOfTriangle = 0, px = 0, py = 0; for (int i = 2; i < pg.size(); i++) { areaOfTriangle = cross(pg[i - 1] - pg[0], pg[i] - pg[0]); areaOfPolygon += areaOfTriangle; px += areaOfTriangle * (pg[0].x + pg[i - 1].x + pg[i].x); py += areaOfTriangle * (pg[0].y + pg[i - 1].y + pg[i].y); } return point(px / (3.0 * areaOfPolygon), py / (3.0 * areaOfPolygon)); }
bool polygonsIntersect(const polygon &a, const polygon &b) { int na = a.size(), nb = b.size(); for (int i = 0; i < na; ++i) { if (pointInPoly(a[i], b)) return true; } for (int i = 0; i < nb; ++i) { if (pointInPoly(b[i], a)) return true; } for (int i = 0; i < na; ++i) { for (int j = 0; j < nb; ++j) { int xa1 = a[i].first, ya1 = a[i].second; int xa2 = a[(i + 1) % na].first, ya2 = a[(i + 1) % na].second; int xb1 = b[j].first, yb1 = b[j].second; int xb2 = b[(j + 1) % nb].first, yb2 = b[(j + 1) % nb].second; if (segment_segment_intersection(xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2)) { return true; } } } return false; }
point getCentroid2(polygon &pg) { double areaOfPolygon = 0, areaOfTriangle = 0, px = 0, py = 0; int n = pg.size(); for (int i = 0; i < n; i++) { areaOfTriangle = cross(pg[i], pg[(i + 1) % n]); areaOfPolygon += areaOfTriangle; px += areaOfTriangle * (pg[i].x + pg[(i + 1) % n].x); py += areaOfTriangle * (pg[i].y + pg[(i + 1) % n].y); } return point(px / (3.0 * areaOfPolygon), py / (3.0 * areaOfPolygon)); }
result lineIntersectsPolygon(line & l, polygon & P) { result points; point prev = P[0]; for (size_t i = 1; i < P.size(); i++) { point cur = P[i]; segment s = {prev, cur}; if (lineIntersectsSegment(l, s)) { points.insert(i - 1); } prev = cur; } return points; }
// 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]); }; }
// (a,b) 를 포함하는 직선으로 다각형 p 를 자른 뒤, (a,b) 의 왼쪽에 있는 부분들을 반환한다 polygon cutPoly(const polygon& p, const vector2& a, const vector2& b) { int n = p.size(); vector<bool> inside(n); for(int i = 0; i < n; ++i) inside[i] = ((b-a).cross(p[i]-a) >= 0); // 이외의 경우에는 일부는 직선 왼쪽에, 일부는 직선 오른쪽에 떨어진다 polygon ret; for(int i = 0; i < n; ++i) { int j = (i + 1) % n; if(inside[i]) ret.push_back(p[i]); if(inside[i] != inside[j]) { vector2 intersection; assert(lineIntersection(p[i], p[j], a, b, intersection)); ret.push_back(intersection); } } return ret; }