From 414b6f1422dff0346d41fcd6edea922c48f4c563 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9s=20Mej=C3=ADa?= Date: Fri, 7 Oct 2011 11:46:24 -0500 Subject: [PATCH] Testing some geometry routines in C++ --- 11665 - Chinese Ink/11665.2.cpp | 221 +++++++++++++++++++++++++++++++++++++ 11665 - Chinese Ink/11665.3.cpp | 218 ++++++++++++++++++++++++++++++++++++ 11665 - Chinese Ink/11665.cpp | 237 ++++++++++++++++++++++++++++++++++++++++ 11665 - Chinese Ink/a.out | Bin 0 -> 75032 bytes 11665 - Chinese Ink/in.txt | 20 ++++ 5 files changed, 696 insertions(+) create mode 100644 11665 - Chinese Ink/11665.2.cpp create mode 100644 11665 - Chinese Ink/11665.3.cpp create mode 100644 11665 - Chinese Ink/11665.cpp create mode 100755 11665 - Chinese Ink/a.out create mode 100644 11665 - Chinese Ink/in.txt diff --git a/11665 - Chinese Ink/11665.2.cpp b/11665 - Chinese Ink/11665.2.cpp new file mode 100644 index 0000000..2a4cd47 --- /dev/null +++ b/11665 - Chinese Ink/11665.2.cpp @@ -0,0 +1,221 @@ +// Accepted +using namespace std; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define foreach(x, v) for (typeof (v).begin() x=(v).begin(); x !=(v).end(); ++x) +#define For(i, a, b) for (int i=(a); i<(b); ++i) +#define D(x) cout << #x " is " << x << endl + +#define EPS 1e-9 + +typedef pair point; +typedef vector< point > polygon; + +vector< polygon > polygons; + +const int MAXN = 50; +int p[MAXN]; + +int find(int u) { + return p[u] == u ? u : p[u] = find(p[u]); +} + +void link(int u, int v) { + if (find(u) != find(v)) { + p[find(u)] = find(v); + } +} + +// Polar angle +// Returns an angle in the range [0, 2*Pi) of a given Cartesian point. +// If the point is (0,0), -1.0 is returned. +// REQUIRES: +// include math.h +// define EPS 0.000000001, or your choice +// P has members x and y. +double polarAngle( point p ) { + double x = p.first, y = p.second; + if(fabs(x) <= EPS && fabs(y) <= EPS) return -1.0; + if(fabs(x) <= EPS) return (y > EPS ? 1.0 : 3.0) * acos(0); + double theta = atan(1.0 * y / x); + if(x > EPS) return(y >= -EPS ? theta : (4*acos(0) + theta)); + return(2 * acos( 0 ) + theta); +} + +//Point inside polygon +// Returns true iff p is inside poly. +// PRE: The vertices of poly are ordered (either clockwise or +// counter-clockwise. +// POST: Modify code inside to handle the special case of "on +// an edge". +// REQUIRES: +// polarAngle() +// include math.h +// include vector +// define EPS 0.000000001, or your choice +bool pointInPoly( point p, const polygon &poly ) { + int n = poly.size(); + double ang = 0.0; + for(int i = n - 1, j = 0; j < n; i = j++){ + point v( poly[i].first - p.first, poly[i].second - p.second ); + point w( poly[j].first - p.first, poly[j].second - p.second ); + double va = polarAngle(v); + double wa = polarAngle(w); + double xx = wa - va; + if(va < -0.5 || wa < -0.5 || fabs(fabs(xx)-2*acos(0)) < EPS){ + // POINT IS ON THE EDGE + return true; + assert( false ); + ang += 2 * acos( 0 ); + continue; + } + if( xx < -2 * acos( 0 ) ) ang += xx + 4 * acos( 0 ); + else if( xx > 2 * acos( 0 ) ) ang += xx - 4 * acos( 0 ); + else ang += xx; + } + return( ang * ang > 1.0 ); +} + + +/* + Returns true if point (x, y) lies inside (or in the border) + of box defined by points (x0, y0) and (x1, y1). +*/ +bool point_in_box(double x, double y, + double x0, double y0, + double x1, double y1){ + return + min(x0, x1) <= x && x <= max(x0, x1) && + min(y0, y1) <= y && y <= max(y0, y1); +} + + +int direction(int pix, int piy, int pjx, int pjy, int pkx, int pky) { + return (pkx - pix) * (pjy - piy) - (pky - piy) * (pjx - pix); +} + +/* + Finds the intersection between two segments (Not infinite + lines!) + Segment 1 goes from point (x0, y0) to (x1, y1). + Segment 2 goes from point (x2, y2) to (x3, y3). + + (Can be modified to find the intersection between a segment + and a line) + + Handles the case when the 2 segments are: + *Parallel but don't lie on the same line (No intersection) + *Parallel and both lie on the same line (Infinite + *intersections or no intersections) + *Not parallel (One intersection or no intersections) + + Returns true if the segments do intersect in any case. +*/ +bool segment_segment_intersection(int x1, int y1, + int x2, int y2, + + int x3, int y3, + int x4, int y4){ + + int d1 = direction(x3, y3, x4, y4, x1, y1); + int d2 = direction(x3, y3, x4, y4, x2, y2); + int d3 = direction(x1, y1, x2, y2, x3, y3); + int d4 = direction(x1, y1, x2, y2, x4, y4); + bool b1 = d1 > 0 and d2 < 0 or d1 < 0 and d2 > 0; + bool b2 = d3 > 0 and d4 < 0 or d3 < 0 and d4 > 0; + if (b1 and b2) return true; + if (d1 == 0 and point_in_box(x1, y1, x3, y3, x4, y4)) return true; + if (d2 == 0 and point_in_box(x2, y2, x3, y3, x4, y4)) return true; + if (d3 == 0 and point_in_box(x3, y3, x1, y1, x2, y2)) return true; + if (d4 == 0 and point_in_box(x4, y4, x1, y1, x2, y2)) return true; + return false; +} + +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; +} + + +void solve() { + int n = polygons.size(); + for (int i = 0; i < n; ++i) { + p[i] = i; + } + + for (int i = 0; i < n; ++i) { + for (int j = i + 1; j < n; ++j) { + if (polygonsIntersect(polygons[i], polygons[j])) { + link(i, j); + } + } + } + set ans; + for (int i = 0; i < n; ++i) { + ans.insert(find(i)); + } + cout << ans.size() << endl; +} + + +int main(){ + int n; + while (cin >> n) { + if (n == 0) break; + string s; getline(cin, s); + polygons.clear(); + for (int i = 0; i < n; ++i){ + polygons.push_back(polygon()); + getline(cin, s); + stringstream sin(s); + int x, y; + while (sin >> x >> y) { + polygons.back().push_back(point(x, y)); + } + assert(polygons.back().size() >= 3); + } + assert(polygons.size() == n); + + solve(); + } + return 0; +} \ No newline at end of file diff --git a/11665 - Chinese Ink/11665.3.cpp b/11665 - Chinese Ink/11665.3.cpp new file mode 100644 index 0000000..a539ac5 --- /dev/null +++ b/11665 - Chinese Ink/11665.3.cpp @@ -0,0 +1,218 @@ +// Accepted +using namespace std; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define foreach(x, v) for (typeof (v).begin() x=(v).begin(); x !=(v).end(); ++x) +#define For(i, a, b) for (int i=(a); i<(b); ++i) +#define D(x) cout << #x " is " << x << endl + +#define EPS 1e-9 + +typedef pair point; +typedef vector< point > polygon; + +vector< polygon > polygons; + +const int MAXN = 50; +int p[MAXN]; + +int find(int u) { + return p[u] == u ? u : p[u] = find(p[u]); +} + +void link(int u, int v) { + if (find(u) != find(v)) { + p[find(u)] = find(v); + } +} + +// Polar angle +// Returns an angle in the range [0, 2*Pi) of a given Cartesian point. +// If the point is (0,0), -1.0 is returned. +// REQUIRES: +// include math.h +// define EPS 0.000000001, or your choice +// P has members x and y. +double polarAngle( point p ) { + double x = p.first, y = p.second; + if(fabs(x) <= EPS && fabs(y) <= EPS) return -1.0; + if(fabs(x) <= EPS) return (y > EPS ? 1.0 : 3.0) * acos(0); + double theta = atan(1.0 * y / x); + if(x > EPS) return(y >= -EPS ? theta : (4*acos(0) + theta)); + return(2 * acos( 0 ) + theta); +} + +//Point inside polygon +// Returns true iff p is inside poly. +// PRE: The vertices of poly are ordered (either clockwise or +// counter-clockwise. +// POST: Modify code inside to handle the special case of "on +// an edge". +// REQUIRES: +// polarAngle() +// include math.h +// include vector +// define EPS 0.000000001, or your choice +bool pointInPoly( point p, const polygon &poly ) { + int n = poly.size(); + double ang = 0.0; + for(int i = n - 1, j = 0; j < n; i = j++){ + point v( poly[i].first - p.first, poly[i].second - p.second ); + point w( poly[j].first - p.first, poly[j].second - p.second ); + double va = polarAngle(v); + double wa = polarAngle(w); + double xx = wa - va; + if(va < -0.5 || wa < -0.5 || fabs(fabs(xx)-2*acos(0)) < EPS){ + // POINT IS ON THE EDGE + return true; + assert( false ); + ang += 2 * acos( 0 ); + continue; + } + if( xx < -2 * acos( 0 ) ) ang += xx + 4 * acos( 0 ); + else if( xx > 2 * acos( 0 ) ) ang += xx - 4 * acos( 0 ); + else ang += xx; + } + return( ang * ang > 1.0 ); +} + + +/* + Returns true if point (x, y) lies inside (or in the border) + of box defined by points (x0, y0) and (x1, y1). +*/ +bool point_in_box(double x, double y, + double x0, double y0, + double x1, double y1){ + return + min(x0, x1) <= x && x <= max(x0, x1) && + min(y0, y1) <= y && y <= max(y0, y1); +} + + +/* + Finds the intersection between two segments (Not infinite + lines!) + Segment 1 goes from point (x0, y0) to (x1, y1). + Segment 2 goes from point (x2, y2) to (x3, y3). + + (Can be modified to find the intersection between a segment + and a line) + + Handles the case when the 2 segments are: + *Parallel but don't lie on the same line (No intersection) + *Parallel and both lie on the same line (Infinite + *intersections or no intersections) + *Not parallel (One intersection or no intersections) + + Returns true if the segments do intersect in any case. +*/ +bool segment_segment_intersection(int x1, int y1, + int x2, int y2, + + int x3, int y3, + int x4, int y4){ + + int d1 = (x1 - x3) * (y4 - y3) - (y1 - y3) * (x4 - x3); + int d2 = (x2 - x3) * (y4 - y3) - (y2 - y3) * (x4 - x3); + int d3 = (x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1); + int d4 = (x4 - x1) * (y2 - y1) - (y4 - y1) * (x2 - x1); + + bool b1 = d1 > 0 and d2 < 0 or d1 < 0 and d2 > 0; + bool b2 = d3 > 0 and d4 < 0 or d3 < 0 and d4 > 0; + if (b1 and b2) return true; + if (d1 == 0 and point_in_box(x1, y1, x3, y3, x4, y4)) return true; + if (d2 == 0 and point_in_box(x2, y2, x3, y3, x4, y4)) return true; + if (d3 == 0 and point_in_box(x3, y3, x1, y1, x2, y2)) return true; + if (d4 == 0 and point_in_box(x4, y4, x1, y1, x2, y2)) return true; + return false; +} + +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; +} + + +void solve() { + int n = polygons.size(); + for (int i = 0; i < n; ++i) { + p[i] = i; + } + + for (int i = 0; i < n; ++i) { + for (int j = i + 1; j < n; ++j) { + if (polygonsIntersect(polygons[i], polygons[j])) { + link(i, j); + } + } + } + set ans; + for (int i = 0; i < n; ++i) { + ans.insert(find(i)); + } + cout << ans.size() << endl; +} + + +int main(){ + int n; + while (cin >> n) { + if (n == 0) break; + string s; getline(cin, s); + polygons.clear(); + for (int i = 0; i < n; ++i){ + polygons.push_back(polygon()); + getline(cin, s); + stringstream sin(s); + int x, y; + while (sin >> x >> y) { + polygons.back().push_back(point(x, y)); + } + assert(polygons.back().size() >= 3); + } + assert(polygons.size() == n); + + solve(); + } + return 0; +} \ No newline at end of file diff --git a/11665 - Chinese Ink/11665.cpp b/11665 - Chinese Ink/11665.cpp new file mode 100644 index 0000000..435cd2d --- /dev/null +++ b/11665 - Chinese Ink/11665.cpp @@ -0,0 +1,237 @@ +// Accepted +using namespace std; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define foreach(x, v) for (typeof (v).begin() x=(v).begin(); x !=(v).end(); ++x) +#define For(i, a, b) for (int i=(a); i<(b); ++i) +#define D(x) cout << #x " is " << x << endl + +#define EPS 1e-9 + +typedef pair point; +typedef vector< point > polygon; + +vector< polygon > polygons; + +const int MAXN = 50; +int p[MAXN]; + +int find(int u) { + return p[u] == u ? u : p[u] = find(p[u]); +} + +void link(int u, int v) { + if (find(u) != find(v)) { + p[find(u)] = find(v); + } +} + +// Polar angle +// Returns an angle in the range [0, 2*Pi) of a given Cartesian point. +// If the point is (0,0), -1.0 is returned. +// REQUIRES: +// include math.h +// define EPS 0.000000001, or your choice +// P has members x and y. +double polarAngle( point p ) { + double x = p.first, y = p.second; + if(fabs(x) <= EPS && fabs(y) <= EPS) return -1.0; + if(fabs(x) <= EPS) return (y > EPS ? 1.0 : 3.0) * acos(0); + double theta = atan(1.0 * y / x); + if(x > EPS) return(y >= -EPS ? theta : (4*acos(0) + theta)); + return(2 * acos( 0 ) + theta); +} + +//Point inside polygon +// Returns true iff p is inside poly. +// PRE: The vertices of poly are ordered (either clockwise or +// counter-clockwise. +// POST: Modify code inside to handle the special case of "on +// an edge". +// REQUIRES: +// polarAngle() +// include math.h +// include vector +// define EPS 0.000000001, or your choice +bool pointInPoly( point p, const polygon &poly ) { + int n = poly.size(); + double ang = 0.0; + for(int i = n - 1, j = 0; j < n; i = j++){ + point v( poly[i].first - p.first, poly[i].second - p.second ); + point w( poly[j].first - p.first, poly[j].second - p.second ); + double va = polarAngle(v); + double wa = polarAngle(w); + double xx = wa - va; + if(va < -0.5 || wa < -0.5 || fabs(fabs(xx)-2*acos(0)) < EPS){ + // POINT IS ON THE EDGE + return true; + assert( false ); + ang += 2 * acos( 0 ); + continue; + } + if( xx < -2 * acos( 0 ) ) ang += xx + 4 * acos( 0 ); + else if( xx > 2 * acos( 0 ) ) ang += xx - 4 * acos( 0 ); + else ang += xx; + } + return( ang * ang > 1.0 ); +} + + +/* + Returns true if point (x, y) lies inside (or in the border) + of box defined by points (x0, y0) and (x1, y1). +*/ +bool point_in_box(double x, double y, + double x0, double y0, + double x1, double y1){ + return + min(x0, x1) <= x && x <= max(x0, x1) && + min(y0, y1) <= y && y <= max(y0, y1); +} + +/* + Finds the intersection between two segments (Not infinite + lines!) + Segment 1 goes from point (x0, y0) to (x1, y1). + Segment 2 goes from point (x2, y2) to (x3, y3). + + (Can be modified to find the intersection between a segment + and a line) + + Handles the case when the 2 segments are: + *Parallel but don't lie on the same line (No intersection) + *Parallel and both lie on the same line (Infinite + *intersections or no intersections) + *Not parallel (One intersection or no intersections) + + Returns true if the segments do intersect in any case. +*/ +bool segment_segment_intersection(double x0, double y0, + double x1, double y1, + + double x2, double y2, + double x3, double y3){ + double t0 = (y3-y2)*(x0-x2)-(x3-x2)*(y0-y2); + double t1 = (x1-x0)*(y2-y0)-(y1-y0)*(x2-x0); + double det = (y1-y0)*(x3-x2)-(y3-y2)*(x1-x0); + if (fabs(det) < EPS){ + //parallel + if (fabs(t0) < EPS || fabs(t1) < EPS){ + //they lie on same line, but they may or may not intersect. + return (point_in_box(x0, y0, x2, y2, x3, y3) || + point_in_box(x1, y1, x2, y2, x3, y3) || + point_in_box(x2, y2, x0, y0, x1, y1) || + point_in_box(x3, y3, x0, y0, x1, y1)); + }else{ + //just parallel, no intersection + return false; + } + }else{ + t0 /= det; + t1 /= det; + /* + 0 <= t0 <= 1 iff the intersection point lies in segment 1. + 0 <= t1 <= 1 iff the intersection point lies in segment 2. + */ + if (0.0 <= t0 && t0 <= 1.0 && 0.0 <= t1 && t1 <= 1.0){ + double x = x0 + t0*(x1-x0); + double y = y0 + t0*(y1-y0); + //intersection is point (x, y) + return true; + } + //the intersection points doesn't lie on both segments. + return false; + } +} + + + + +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; +} + + +void solve() { + int n = polygons.size(); + for (int i = 0; i < n; ++i) { + p[i] = i; + } + + for (int i = 0; i < n; ++i) { + for (int j = i + 1; j < n; ++j) { + if (polygonsIntersect(polygons[i], polygons[j])) { + link(i, j); + } + } + } + set ans; + for (int i = 0; i < n; ++i) { + ans.insert(find(i)); + } + cout << ans.size() << endl; +} + + +int main(){ + int n; + while (cin >> n) { + if (n == 0) break; + string s; getline(cin, s); + polygons.clear(); + for (int i = 0; i < n; ++i){ + polygons.push_back(polygon()); + getline(cin, s); + stringstream sin(s); + int x, y; + while (sin >> x >> y) { + polygons.back().push_back(point(x, y)); + } + assert(polygons.back().size() >= 3); + } + assert(polygons.size() == n); + + solve(); + } + return 0; +} \ No newline at end of file diff --git a/11665 - Chinese Ink/a.out b/11665 - Chinese Ink/a.out new file mode 100755 index 0000000000000000000000000000000000000000..e8f4b0536bc6c4dad68be58e5d54447f24bb2118 GIT binary patch literal 75032 zcwX&&d3=?{_4i}}B3lAR2nZ4oFf7I-1V~scNUmOFF%n`?(Z_6%Xf~4@1WPO$pj-ns zwb)WcOIu!l)RijI)FOmMh{&taqKy=FGj%-S2au{r&NhPv$(& znVIjInKNgW=RV7M_uQ%Py9p5%A;gMsAw*9IaZy67S`jAjZvX@<1Wn7Fev{=6%e-5J z$6uIdl*b>+X$(g>^DPVJyQUF-g&Tl*sGH~lA&R3l%~r6~=FH|UZ*z>4cPQP-hYQ1B zq-#lU3P zD_ELWP;S#~Il1og>N2Ig55k%OPjJ#Wa z{KQp%$osPs92X@eWu;EuRbD*H(+wD7{~G5Q{L{4DO6M%)DKBb`#JJUY|X4 z?kr2jOf@FzIPWGWkAHDb$RqZHQPwc9%p?Pk`M1JhE8?z&;~Ox?fuiDe3$bOeoIm0q zG#nG+3>-I{l>&Oec_xd9;_w!P_aF=vzW-WI3GtGbM)wx7uW&uPuBx))y5geT>++Ws z=X3g%Le^vSo%O@|hNlgDEV4T1&buQQV;|HDIY*856#HNQQ|novKWt~3kZqzl`ZDaP zZqBwtsI=whjTw_TArbUYl#q{|Ds9>wp;Ypt{@eTwHDo4voG$>xAq$AWUta|tK0N! zl)ksNTGwa6S^D1SCmL2Z*v4YgBu7$`mntlGR>4*H0;|2c-fFMfYPDx?0mW_6?@NcQ zosCwzrNvrn*(y()K%Wq*TlAe%Ah{M)ZE1$&7C1KUx10{M9HNwN;HIC;
<#j8nPm8KITd#3|ThkP{*&Dc~ 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 literal 0 HcwPel00001 diff --git a/11665 - Chinese Ink/in.txt b/11665 - Chinese Ink/in.txt new file mode 100644 index 0000000..b73ba4a --- /dev/null +++ b/11665 - Chinese Ink/in.txt @@ -0,0 +1,20 @@ +5 +35 29 179 111 19 145 +183 22 305 22 305 80 183 80 +232 49 361 49 361 178 232 178 +137 94 188 156 112 164 +79 144 129 143 129 193 79 193 +2 +20 20 30 20 30 30 20 30 +40 40 40 50 50 50 50 40 +2 +20 20 30 20 30 30 20 30 +30 30 40 30 40 40 30 40 +3 +20 20 40 20 40 40 20 40 +50 30 60 20 70 50 +60 40 50 30 30 50 +2 +0 0 10 0 10 5 0 5 +2 -2 3 -2 3 7 2 7 +0 -- 2.11.4.GIT