static int edgesIntersect(Point * P, Point * Q, int n, int m) { int a = 0; int b = 0; int aa = 0; int ba = 0; int a1, b1; Point A, B; double cross; int bHA, aHB; Point p; int inflag = Unknown; /* int i = 0; */ /* int Reset = 0; */ do { a1 = (a + n - 1) % n; b1 = (b + m - 1) % m; subpt(&A, P[a], P[a1]); subpt(&B, Q[b], Q[b1]); cross = area_2(origin, A, B); bHA = leftOf(P[a1], P[a], Q[b]); aHB = leftOf(Q[b1], Q[b], P[a]); /* If A & B intersect, update inflag. */ if (intersection(P[a1], P[a], Q[b1], Q[b], &p)) return 1; /* Advance rules. */ if ((cross == 0) && !bHA && !aHB) { if (inflag == Pin) advance(b, ba, m); else advance(a, aa, n); } else if (cross >= 0) if (bHA) advance(a, aa, n); else { advance(b, ba, m); } else { /* if ( cross < 0 ) */ if (aHB) advance(b, ba, m); else advance(a, aa, n); } } while (((aa < n) || (ba < m)) && (aa < 2 * n) && (ba < 2 * m)); return 0; }
/* Intersection area */ template<class K> typename K::FT intersection_area_two_slabs(const Rectangle_2<K>& a, const Rectangle_2<K> &b) { typedef typename K::Vector_2 Vector_2; typedef typename K::Line_2 Line_2; typedef typename K::Point_2 Point_2; typedef typename K::FT FT; Origin O; if(a.is_degenerate() || b.is_degenerate()) return 0; std::vector<Vector_2> v; std::vector<Line_2> l; for(unsigned int i=0; i<4; ++i) { v.push_back(b[i]-O); l.push_back(b.line(i)); } const Vector_2& n = a.normal(); FT r = a.ratio(); FT n2 = n.squared_length(); FT rn2 = r*r*n2; Vector_2 vc(a.center()-O); Vector_2 trn(-r*n.y(),r*n.x()); FT ctrn = vc*trn; FT cn = vc*n; Vector_2 ln[] = { n, trn }; FT lc[] = { cn+n2, ctrn+rn2, cn-n2, ctrn-rn2 }; // basically it is the iterative intersection of the convex polygon initialized with b // with the 2 slabs line0/line2 and line1/line3. for(unsigned int i=0; i<2; ++i) { int begin0=-1, end0=-1; int begin1=-1, end1=-1; unsigned int n=v.size(); for(unsigned int j=0; j<n; ++j) { FT dot = ln[i]*v[j]; if( dot>lc[i]) { if(end0==-1 && begin0!=-1) end0=j; if(begin1<=end1) begin1=j; } else { if(begin0<=end0) begin0=j; if(dot<lc[i+2]) { if(end1==-1 && begin1!=-1) end1=j; } else { if(begin1<=end1) begin1=j; } } } if(begin0==-1 || begin1==-1 ) return 0; // outside the slab if(end0 ==-1) { if(begin0!=0) end0=0; else begin0=begin1; } if(end1 ==-1) { if(begin1!=0) end1=0; else { if(end0==-1) continue; // inside the slab begin1=begin0; } } std::vector<Vector_2> w; std::vector<Line_2> m; if(end0!=-1) { // cut outside line(i+1) for(int j=begin1; j!=end0; j=(j+1)%n) { w.push_back(v[j]); m.push_back(l[j]); } Point_2 inter(O); Line_2 li(ln[i].x(),ln[i].y(),-lc[i]); intersection(l[(end0+n-1)%n],li).assign(inter); w.push_back(inter-O); m.push_back(li); m.push_back(l[(begin0+n-1)%n]); intersection(li,m.back()).assign(inter); w.push_back(inter-O); } if(end1!=-1) { // cut outside line(i+3) for(int j=begin0; j!=end1; j=(j+1)%n) { w.push_back(v[j]); m.push_back(l[j]); } Point_2 inter(O); Line_2 li(ln[i].x(),ln[i].y(),-lc[i+2]); intersection(l[(end1+n-1)%n],li).assign(inter); w.push_back(inter-O); m.push_back(li); m.push_back(l[(begin1+n-1)%n]); intersection(li,m.back()).assign(inter); w.push_back(inter-O); } std::swap(v,w); std::swap(l,m); } std::vector<Point_2> p; for(unsigned int i=0; i<v.size(); ++i) { p.push_back(O+v[i]); } FT area; area_2(p.begin(),p.end(),area); return abs(area); }