void merge_crossings(Crossings &a, Crossings &b, unsigned i) { Crossings n; sort_crossings(b, i); n.resize(a.size() + b.size()); std::merge(a.begin(), a.end(), b.begin(), b.end(), n.begin(), CrossingOrder(i)); a = n; }
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; }
Edges edges(Path const &p, Crossings const &cr, unsigned ix) { Edges ret = Edges(); EndPoint prev; for(unsigned i = 0; i <= cr.size(); i++) { double t = cr[i == cr.size() ? 0 : i].getTime(ix); Point pnt = p.pointAt(t); Point normal = p.pointAt(t+0.01) - pnt; normal.normalize(); std::cout << pnt << "\n"; EndPoint cur(pnt, normal, t); if(i == 0) { prev = cur; continue; } ret.push_back(Edge(prev, cur, ix, false)); ret.push_back(Edge(prev, cur, ix, true)); prev = cur; } return ret; }
CrossingSet crossings_among(std::vector<Path> const &p) { CrossingSet results(p.size(), Crossings()); if(p.empty()) return results; SimpleCrosser cc; std::vector<std::vector<unsigned> > cull = sweep_bounds(bounds(p)); for(unsigned i = 0; i < cull.size(); i++) { Crossings res = self_crossings(p[i]); for(unsigned k = 0; k < res.size(); k++) { res[k].a = res[k].b = i; } merge_crossings(results[i], res, i); flip_crossings(res); merge_crossings(results[i], res, i); for(unsigned jx = 0; jx < cull[i].size(); jx++) { unsigned j = cull[i][jx]; Crossings res = cc.crossings(p[i], p[j]); for(unsigned k = 0; k < res.size(); k++) { res[k].a = i; res[k].b = j; } merge_crossings(results[i], res, i); merge_crossings(results[j], res, j); } } return results; }
/** * This is the main routine of "MonoCrosser", and implements a monotonic strategy on multiple curves. * Finds crossings between two sets of paths, yielding a CrossingSet. [0, a.size()) of the return correspond * to the sorted crossings of a with paths of b. The rest of the return, [a.size(), a.size() + b.size()], * corresponds to the sorted crossings of b with paths of a. * * This function does two sweeps, one on the bounds of each path, and after that cull, one on the curves within. * This leads to a certain amount of code complexity, however, most of that is factored into the above functions */ CrossingSet MonoCrosser::crossings(std::vector<Path> const &a, std::vector<Path> const &b) { if(b.empty()) return CrossingSet(a.size(), Crossings()); CrossingSet results(a.size() + b.size(), Crossings()); if(a.empty()) return results; std::vector<std::vector<double> > splits_a = paths_mono_splits(a), splits_b = paths_mono_splits(b); std::vector<std::vector<Rect> > bounds_a = split_bounds(a, splits_a), bounds_b = split_bounds(b, splits_b); std::vector<Rect> bounds_a_union, bounds_b_union; for(unsigned i = 0; i < bounds_a.size(); i++) bounds_a_union.push_back(union_list(bounds_a[i])); for(unsigned i = 0; i < bounds_b.size(); i++) bounds_b_union.push_back(union_list(bounds_b[i])); std::vector<std::vector<unsigned> > cull = sweep_bounds(bounds_a_union, bounds_b_union); Crossings n; for(unsigned i = 0; i < cull.size(); i++) { for(unsigned jx = 0; jx < cull[i].size(); jx++) { unsigned j = cull[i][jx]; unsigned jc = j + a.size(); Crossings res; //Sweep of the monotonic portions std::vector<std::vector<unsigned> > cull2 = sweep_bounds(bounds_a[i], bounds_b[j]); for(unsigned k = 0; k < cull2.size(); k++) { for(unsigned lx = 0; lx < cull2[k].size(); lx++) { unsigned l = cull2[k][lx]; mono_pair(a[i], splits_a[i][k-1], splits_a[i][k], b[j], splits_b[j][l-1], splits_b[j][l], res, .1); } } for(unsigned k = 0; k < res.size(); k++) { res[k].a = i; res[k].b = jc; } merge_crossings(results[i], res, i); merge_crossings(results[i], res, jc); } } return results; }
void offset_crossings(Crossings &cr, double a, double b) { for(unsigned i = 0; i < cr.size(); i++) { cr[i].ta += a; cr[i].tb += b; } }
void flip_crossings(Crossings &crs) { for(unsigned i = 0; i < crs.size(); i++) crs[i] = Crossing(crs[i].tb, crs[i].ta, crs[i].b, crs[i].a, !crs[i].dir); }