You are on page 1of 5

double dvac(int low, int high) { double d = centerdist;

if(low < high) { double l = (r1 * r1 - r2 * r2 + d *


if(low == high - 1) { d) / (2 * d);
return dist(data[low], double h = sqrt(r1 * r1 - l * l);
data[high]); if (abs(h) < EPS) { //only one
} solution
int mid = (low + high) / 2; double x = ((l / d) * (x2 - x1) +
double d1 = dvac(low, mid); (h / d) * (y2 - y1) + x1);
double d2 = dvac(mid + 1, high); double y = ((l / d) * (y2 - y1)
double dp = min(d1, d2); - (h / d) * (x2 - x1) + y1);
double d3 = 10000; cout << "(" << x + EPS2 << ","
for(int i = mid; i >= low; i--) { << y + EPS2 << ")\n";
double temp = continue;
dist(point(data[i].x, 0), }
point(data[mid].x, 0)); double x = ((l / d) * (x2 - x1) + (h
if(temp > dp - EPS) break; / d) * (y2 - y1) + x1);
for(int j = mid + 1; j <= high; double y = ((l / d) * (y2 - y1) - (h
j++) { / d) * (x2 - x1) + y1);
double temp2 = vector <point> ans;
dist(point(data[i].x, 0), point(data[j].x, ans.push_back(point(x, y));
0)); x = ((l / d) * (x2 - x1) - (h / d) *
if(temp2 > dp - EPS) break; (y2 - y1) + x1);
d3 = min(d3, dist(data[i], y = ((l / d) * (y2 - y1) + (h / d) *
data[j])); (x2 - x1) + y1);
} ans.push_back(point(x, y));
} sort(ans.begin(), ans.end());
return min(dp, d3); cout << "(" << ans[0].x + EPS2 <<
} "," << ans[0].y + EPS2 << ")";
return 10000; cout << "(" << ans[1].x + EPS2 <<
} "," << ans[1].y + EPS2 << ")\n";
//circles intersection }
/*Follows Salix idea: }
https://math.stackexchange.com/questions/2561
00/how-can-i-find-the-points-at-which-two-cir struct point {
cles-intersect */ double x , y ;
void circles_intersection() { point () {}
double x1, x2, y1, y2, r1, r2; point(double xx, double yy) {
while (cin >> x1 >> y1 >> r1 >> x2 >> y2 x = xx; y = yy;
>> r2) { }
double centerdist = dist(point(x1, bool operator < (const point &other)
y1), point(x2, y2)); const{
if (r1 > EPS and centerdist < EPS if( abs(x - other.x) > EPS) return x <
and abs(r1 - r2) < EPS) { other.x;
cout << "THE CIRCLES ARE THE return y < other.y;
SAME\n"; }
continue; bool operator == (const point &other)
} const{
if (r1 < EPS and r2 < EPS and return (abs(x - other.x) < E PS &&
centerdist < EPS) { abs(y - other.y) < EPS);
cout << "(" << x1 + EPS2 << "," }
<< y1 + EPS2 << ")\n"; };
continue; double dist(point p1, point p 2) { //
} Euclidean distance
if (centerdist < EPS) { // hypot(dx, dy) returns sqrt(dx * dx + dy *
cout << "NO INTERSECTION\n"; dy)
continue; return h ypot(p1.x - p2.x, p1.y - p2.y); }
} point rotate(point p, double t heta) {
if (centerdist > r1 + r2 + EPS) { double r ad = theta * PI / 180;
cout << "NO INTERSECTION\n"; return p oint(p.x * cos(rad) - p.y *
continue; sin(rad),
} p.x * sin(rad) + p.y *
if (centerdist + r2 < r1 - EPS || cos(rad));
centerdist + r1 < r2 - EPS) { }
cout << "NO INTERSECTION\n"; point rotatewrto(point p, p oint o, double
continue; theta) {
} double r ad = theta * PI / 180;
return point(o.x + (p.x - o.x) * cos(rad) // and r is the same as rInCircle
- (p.y - o.y) * sin(rad), int inCircle(point p1, point p 2, point p3,
o.y + (p.x - o.x) * sin(rad) + (p.y - o.y) point &ctr, double &r) {
* cos(rad)); r = rInCircle(p1, p2, p3);
} if ( fabs(r) < EPS) return 0 ; // no
struct vec { double x, y; // name: vec is inCircle center
different from STL vector line l1, l2; // compute these two angle
vec(double _x, double _y) : x(_x), y(_y) bisectors
{} double r atio = dist(p1, p2) / dist(p1,
}; p3);
vec toVec(point a, point b) point p = translate(p2, scale(toVec(p2,
{ // convert 2 points to vector a->b p3), ratio / (1 + ratio)));
return vec(b.x - a.x, b.y - a.y); pointsToLine(p1, p, l1);
} ratio = dist(p2, p1) / dist(p2, p3);
vec scale(vec v, double s) { p = translate(p1, scale(toVec(p1, p3),
// nonnegative s = [<1 .. 1 .. >1] ratio / (1 + ratio)));
return vec(v.x * s, v.y * s); pointsToLine(p2, p, l2);
} // shorter.same.longer areIntersect(l1, l2, ctr); // get their
point translate(point p, vec v) { // intersection point
translate p according to v return 1 ; }
return point(p.x + v.x , p.y + v.y);
} bool inPolygon(point p t, const vector< point>
double dot(vec a, vec b) &P) {
{ return (a.x * b.x + a.y * b.y); } if ( (int)P.size() == 0) return false;
double norm_sq(vec v) double s um = 0; // assume the first vertex
{ return v.x * v.x + v.y * v.y; } is equal to the last vertex
double angle(point a, point o, point b ) for (int i = 0; i < (int)P.size()-1 ; i++)
{ // returns angle aob in rad {
vec oa = toVec(o, a), ob = toVec(o, b); if ( ccw(pt, P[i], P[ i+1
]))
return acos(dot(oa, ob) / sqrt(norm_sq(oa) sum += angle(P[i], pt, P[i+1]); //
* norm_sq(ob))); left turn/ccw
} else sum -= angle(P[i], pt, P[i+1]); }
double cross(vec a, vec b) { return a.x * b.y // right turn/cw
- a.y * b.x; } return f abs(fabs(sum) - 2*PI) < EPS; }
// note: to accept collinear points, we have
to change the > 0 struct line{
// returns true if point r is on the left double a
, b
, c;
side of line pq };
bool ccw(point p, point q, point r ) {
return cross(toVec(p, q), toVec(p, r)) > void pointsToLine(point p1, point p2, line
0; } &l) {
// returns true if point r is on the same if ( fabs(p1.x - p2.x) < EPS) { // vertical
line as the line pq line is fine
bool collinear(point p, point q, point r) { l.a = 1 .0; l.b = 0.0; l.c = -p1.x; //
return fabs(cross(toVec(p, q), toVec(p, default values
r))) < EPS; } } else {
int insideCircle(point_i p, point_i c, int r) l.a = -(double) (p1.y - p2.y) / (p1.x -
{ // all integer version p2.x);
int dx = p.x - c.x, dy = p.y - c.y; l.b = 1 .0; // IMPORTANT: we fix the
int Euc = dx * dx + dy * dy, rSq = r * r; value of b to 1.0
// all integer l.c = -(double) (l.a * p1.x) - p1.y;
return Euc < rSq ? 0 : Euc == rSq ? 1 : 2; }
} //inside/border/outside }
double rInCircle(double ab, double bc, double
ca) { bool areParallel(line l1, l ine l2) { // check
return area(ab, bc, ca) / (0.5 * coefficients a & b
perimeter(ab, bc, ca)); } return ( fabs(l1.a-l2.a) < EPS) &&
double rInCircle(point a, point b, point c ) { (fabs(l1.b-l2.b) < EPS); }
return rInCircle(dist(a, b), dist(b, c), bool areSame(line l1, line l2) { // also
dist(c, a)); } check coefficient c
// assumption: the required points/lines return a reParallel(l1 ,l2) && (fabs(l1.c -
functions have been written l2.c) < EPS); }
// returns 1 if there is an inCircle center,
returns 0 otherwise bool areIntersect(line l1, line l2, point &p)
// if this function returns 1, ctr will be {
the inCircle center
if (areParallel(l1, l2)) return false; // y1 = P[i].y; y2 = P[i+1 ].y;
no intersection result += (x1 * y2 - x2 * y1);
// solve system of 2 linear algebraic }
equations with 2 unknowns return a bs(result) / 2.0; }
p.x = (l2.b * l1.c - l1.b * l2.c) / (l2.a bool isConvex(const v ector<point> &P) { //
* l1.b - l1.a * l2.b); returns true if all three
// special case: test for vertical line to int sz = (i nt)P.size(); // consecutive
avoid division by zero vertices of P form the same turns
if (fabs(l1.b) > EPS) p.y = -(l1.a * p.x + if ( sz <= 3) return false; // a point/sz=2
l1.c); or a line/sz=3 is not convex
else p.y = -(l2.a * p.x + l2.c); bool isLeft = ccw(P[0], P[1], P[ 2]); //
return true; remember one result
} for (int i = 1; i < sz-1; i++) // then
// returns the distance from p to the line compare with the others
defined by if ( ccw(P[i], P[i+1], P[(i+2 ) == sz ?
// two points a and b (a and b must be 1 : i+2]) != isLeft)
different) return false; // different sign ->
// the closest point is stored in the 4th this polygon is concave
parameter (byref) return true; } // this polygon is convex
double distToLine(point p, point a , point b, // line segment p-q intersect with line A-B.
point &c) { point lineIntersectSeg(point p , point q,
// formula: c = a + u * ab point A, point B) {
vec ap = toVec(a, p), ab = toVec(a, b); double a = B.y - A.y;
double u = dot(ap, ab) / norm_sq(ab); double b = A.x - B.x;
c = translate(a, scale(ab, u)); // double c = B.x * A.y - A.x * B.y ;
translate a to c double u = fabs(a * p.x + b * p.y + c);
return dist(p, c); double v = fabs(a * q.x + b * q.y + c);
} // Euclidean distance between p and c return p oint((p.x * v + q.x * u) / (u+v),
// returns the distance from p to the line (p.y * v + q.y * u) / (u+v)); }
segment ab defined by // cuts polygon Q along the line formed by
// two points a and b (still OK if a == b) point a -> point b
// the closest point is stored in the 4th // (note: the last point must be the same as
parameter (byref) the first point)
double distToLineSegment(point p, p oint a, vector<point> cutPolygon(point a, p oint b,
point b, point &c) { const vector<point> &Q) {
vec ap = toVec(a, p), ab = toVec(a, b); vector< point> P;
double u = dot(ap, ab) / norm_sq(ab); for (int i = 0; i < (int)Q.size(); i++) {
if (u < 0.0) { c = point(a.x, a.y); // double left1 = cross(toVec(a, b),
closer to a toVec(a, Q[i])), left2 = 0;
return dist(p, a); } // Euclidean if ( i != (int)Q.size()-1) left2 =
distance between p and a cross(toVec(a, b), toVec(a, Q[i+1]));
if (u > 1.0) { c = point(b.x, b.y); // if ( left1 > -EPS) P.push_back(Q[i]);
closer to b // Q[i] is on the left of ab
return dist(p, b); } // Euclidean if ( left1 * left2 < -EPS) // edge
distance between p and b (Q[i], Q[i+1]) crosses line ab
return distToLine(p, a, b, c); } // run P.push_back(lineIntersectSeg(Q[i],
distToLine as above Q[i+1], a, b));
}
double tria(point a, point b, p oint c) { if ( !P.empty() && !(P.back() ==
double area = (a.x * b.y - a.y * b.x + b.x P.front()))
* c.y - b.y * c.x + c.x * a.y - c.y * a.x) / P.push_back(P.front()); // make Ps
2.0; first point = Ps last point
return abs(area); return P ; }
} bool circle2PtsRad(point p1, point p2, double
double perimeter(const vector<point> &P) { r, point & c) {
double result = 0.0; double d 2 = (p1.x - p2.x) * (p1.x - p2.x)
for (int i = 0; i < (int)P.size()-1 ; i++) +
// remember that P[0] = P[n-1] (p1.y - p2.y) * (p1.y - p2.y);
result += dist(P[i], P[i+1]); double d et = r * r / d2 - 0.25;
return result; } if ( det < 0.0) return false;
double h = sqrt(det);
double areap(const vector<point> &P) { c.x = (p1.x + p2.x) * 0.5 + (p1.y - p2.y)
double result = 0.0, x1, y1, x2, y2; * h;
for (int i = 0; i < (int)P.size()-1 ; i++) c.y = (p1.y + p2.y) * 0.5 + (p2.x - p1.x)
{ * h;
x1 = P[i].x; x2 = P[i+1
].x;
return true; } // to get the other center, pivot = P[0]; // use this global variable
reverse p1 and p2 as reference
bool ontri(point tochk, point a, point b, sort(++P.begin(), P.end(), angleCmp); //
point c) { we do not sort P[0]
line ab, bc, ac; // third, the ccw tests
pointsToLine(a, b, ab); pointsToLine(b, c, vector< point> S;
bc); pointsToLine(a, c, ac); S.push_back(P[n-1]); S.push_back(P[0]);
double x = tochk.x, y = tochk.y; S.push_back(P[1]); // initial S
if(x > min(a.x, b.x) - EPS && x < max(a.x, i = 2; // then, we check the rest
b.x) + EPS && y > min(a.y, b.y) - EPS && y < while ( i < n) { // note: N must be >= 3
max(b.y, a.y) + EPS && abs(ab.a * tochk.x + for this method to work
ab.b * tochk.y + ab.c) < EPS) { j = (int)S.size()-1;
return true; if ( ccw(S[j-1], S[j], P[i]))
} S.push_back(P[i++] ); // left turn, accept
else S.pop_back(); } // or pop the top
if(x > min(b.x, c.x) - EPS && x < max(b.x, of S until we have a left turn
c.x) + EPS && y > min(c.y, b.y) - EPS && y < return S ; } // return the result
max(b.y, c.y) + EPS && abs(bc.a * tochk.x + /*CH2: Will accept collinear points but all
bc.b * tochk.y + bc.c) < EPS) { points should be distinct*/
return true; bool cmp(point a, p oint b) { // angle-sorting
} function
if(x > min(a.x, c.x) - EPS && x < max(a.x, if ( collinear(pivot, a, b)) // special
c.x) + EPS && y > min(c.y, a.y) - EPS && y < case
max(a.y, c.y) + EPS && abs(ac.a * tochk.x + {
ac.b * tochk.y + ac.c) < EPS) { if ( dot(toVec(sa, sb), toVec(sa, a)) <
return true; EPS) {
} return d ist(pivot, a) >
return false; dist(pivot, b);
} }
/*CH1: For non collinear points*/ else
return dist(pivot, a) <
point sa, sb; dist(pivot, b); // check which one is closer
point pivot(0, 0); }
bool angleCmp(point a, point b) { // double d 1x = a.x - pivot.x, d1y = a.y -
angle-sorting function pivot.y;
if (collinear(pivot, a, b)) // special double d 2x = b.x - pivot.x, d2y = b.y -
case pivot.y;
return dist(pivot, a) < dist(pivot, return ( atan2(d1y, d1x) - atan2(d2y, d2x))
b); // check which one is closer < 0; } // compare two angles
double d1x = a.x - pivot.x, d1y = a.y -
pivot.y; vector<point> CH2(vector<point> P) { // the
double d2x = b.x - pivot.x, d2y = b.y - content of P may be reshuffled
pivot.y; int i, j, n = (i nt)P.size();
return (atan2(d1y, d1x) - atan2(d2y, d2x)) if ( n <= 3) {
< 0; } // compare two angles if ( !(P[0] == P[n-1]))
vector<point> CH1(vector<point> P) { // the P.push_back(P[0]); // safeguard from corner
content of P may be reshuffled case
int i, j, n = (int)P.size(); return P; } // special case, the CH is
if (n <= 3) { P itself
if (!(P[0] == P[n-1])) // first, find P0 = point with lowest Y and
P.push_back(P[0]); // safeguard from corner if tie: rightmost X
case int P0 = 0;
return P; } // special case, the CH is for (i = 1; i < n; i++)
P itself if ( P[i].y < P[P0].y || (P[i].y ==
// first, find P0 = point with lowest Y and P[P0].y && P[i].x > P[P0].x))
if tie: rightmost X P0 = i;
int P0 = 0; point t emp = P[0]; P[0] = P[P0]; P[P0] =
for (i = 1; i < n; i++) temp; // swap P[P0] with P[0]
if (P[i].y < P[P0].y || (P[i].y == // second, sort points by angle w.r.t. pivot
P[P0].y && P[i].x > P[P0].x)) P0
P0 = i; pivot = P[0]; // use this global variable
point temp = P[0]; P[0] = P[ P0]
; P[P0] = as reference
temp; // swap P[P0] with P[0] sort(++P.begin(), P.end(), angleCmp); //
// second, sort points by angle w.r.t. pivot we do not sort P[0]
P0 sa = P[0], sb = P[1];
sort(++P.begin(), P.end(), cmp);
// to be continued
// continuation from the earlier part
// third, the ccw tests
vector<point> S;
S.push_back(P[n-1]); S.push_back(P[0]);
S.push_back(P[1]); // initial S
i = 2; // then, we check the rest
while (i < n) { // note: N must be >= 3
for this method to work
j = (int)S.size()-1;
if (ccw(S[j-1], S[j], P[
i]) ||
collinear(S[j - 1], S[j], P[i]))
S.push_back(P[i++]); // left turn, accept
else S.pop_back(); } // or pop the top
of S until we have a left turn
return S; } // return the result

bool isinside(point tochk, point a , point b,


point c, double area) {
double area_ = tria(a, b, tochk);
area_ += tria(a, tochk, c);
area_ += tria(tochk, b, c);
return (area_ <= area + EPS)
? true :
false;
}

bool insideoronpolygon(vector<point> poly,


point tochk, int which) {
if(poly.empty()) return false;
if(poly.size() <= 3) {
if(which == 0)
if((poly[0] == tochk &&
cnt[poly[0]] >= 3) || poly[1] == tochk &&
cnt[poly[1]] >= 3) return true;
if(which == 1)
if((poly[0] == tochk &&
cnt2[poly[0]] >= 3) || poly[1] == tochk &&
cnt2[poly[1]] >= 3) return true;
//if(poly[0] == tochk) return true;

return false;
}
double polya = areap(poly);
if(abs(polya) < EPS) { //that means we
have a line;
point a = poly[0], b =
poly[poly.size() - 2];
line ab;
pointsToLine(a, b, ab);
if(tochk.x >= min(a.x, b.x) && tochk.x
<= max(a.x, b.x) && tochk.y >= min(a.y, b.y)
&& tochk.y <= max(a.y, b.y)) {
if(abs(ab.a * tochk.x + ab.b *
tochk.y + ab.c) < EPS) return true;
return false;
}
else return false;
}
double areacmp = 0;
for(int i = 0; i < poly.size() - 1; i++) {
point a = poly[i], b = poly[i + 1];
areacmp += tria(a, b, tochk);
}
return abs(polya - areacmp) < EPS;
}

You might also like