Crossings self_crossings(Path const &p) { Crossings ret; std::vector<std::vector<unsigned> > cull = sweep_bounds(bounds(p)); for(unsigned i = 0; i < cull.size(); i++) { Crossings res = curve_self_crossings(p[i]); offset_crossings(res, i, i); append(ret, res); for(unsigned jx = 0; jx < cull[i].size(); jx++) { unsigned j = cull[i][jx]; res.clear(); pair_intersect(p[i], 0, 1, p[j], 0, 1, res); //if(fabs(int(i)-j) == 1 || fabs(int(i)-j) == p.size()-1) { Crossings res2; for(unsigned k = 0; k < res.size(); k++) { if(res[k].ta != 0 && res[k].ta != 1 && res[k].tb != 0 && res[k].tb != 1) { res2.push_back(res[k]); } } res = res2; //} offset_crossings(res, i, j); append(ret, res); } } return ret; }
Crossings curve_self_crossings(Curve const &a) { Crossings res; std::vector<double> spl; spl.push_back(0); append(spl, curve_mono_splits(a)); spl.push_back(1); for(unsigned i = 1; i < spl.size(); i++) for(unsigned j = i+1; j < spl.size(); j++) pair_intersect(a, spl[i-1], spl[i], a, spl[j-1], spl[j], res); return res; }
/** * This uses the local bounds functions of curves to generically intersect two. * It passes in the curves, time intervals, and keeps track of depth, while * returning the results through the Crossings parameter. */ void pair_intersect(Curve const & A, double Al, double Ah, Curve const & B, double Bl, double Bh, Crossings &ret, unsigned depth=0) { // std::cout << depth << "(" << Al << ", " << Ah << ")\n"; OptRect Ar = A.boundsLocal(Interval(Al, Ah)); if (!Ar) return; OptRect Br = B.boundsLocal(Interval(Bl, Bh)); if (!Br) return; if(! Ar->intersects(*Br)) return; //Checks the general linearity of the function if((depth > 12)) { // || (A.boundsLocal(Interval(Al, Ah), 1).maxExtent() < 0.1 //&& B.boundsLocal(Interval(Bl, Bh), 1).maxExtent() < 0.1)) { double tA, tB, c; if(linear_intersect(A.pointAt(Al), A.pointAt(Ah), B.pointAt(Bl), B.pointAt(Bh), tA, tB, c)) { tA = tA * (Ah - Al) + Al; tB = tB * (Bh - Bl) + Bl; intersect_polish_root(A, tA, B, tB); if(depth % 2) ret.push_back(Crossing(tB, tA, c < 0)); else ret.push_back(Crossing(tA, tB, c > 0)); return; } } if(depth > 12) return; double mid = (Bl + Bh)/2; pair_intersect(B, Bl, mid, A, Al, Ah, ret, depth+1); pair_intersect(B, mid, Bh, A, Al, Ah, ret, depth+1); }
/** A simple wrapper around pair_intersect */ Crossings SimpleCrosser::crossings(Curve const &a, Curve const &b) { Crossings ret; pair_intersect(a, 0, 1, b, 0, 1, ret); return ret; }
Crossings pair_intersect(Curve const & A, Interval const &Ad, Curve const & B, Interval const &Bd) { Crossings ret; pair_intersect(A, Ad.min(), Ad.max(), B, Bd.min(), Bd.max(), ret); return ret; }