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;
}
Example #3
0
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);
}