コード例 #1
0
ファイル: worms.cpp プロジェクト: mental/lib2geom
 void draw(cairo_t *cr, int t) {
     if(t - last_time > path.domain().max()) add_section(random_d2());
     if(t - last_time - length > path.cuts[1]) {
         Piecewise<D2<SBasis> > new_path;
         new_path.push_cut(0);
         for(unsigned i = 1; i < path.size(); i++) {
             new_path.push(path[i], path.cuts[i+1] - path.cuts[1]);
         }
         last_time = t - length;
         path = new_path;
     }
     cairo_set_source_rgb(cr, red, green, blue);
     Piecewise<D2<SBasis> > port = portion(path, std::max(t - last_time - length, 0.), t - last_time);
     cairo_pw_d2_sb(cr, port);
     cairo_stroke(cr);
     
     double d = 4;
     cairo_set_dash(cr, &d, 1, 0);
     for(unsigned i = 1; i < path.size(); i++) {
         if(path[i].at0() != path[i-1].at1()) {
             draw_line_seg(cr, path[i].at0(), path[i-1].at1());
         }
     }
     cairo_stroke(cr);
     cairo_set_dash(cr, &d, 0, 0);
     
     cairo_set_source_rgb(cr, 0., 0., 1.);
     dot_plot(cr, path, std::max(t - last_time - length, 0.), t - last_time);
 }
コード例 #2
0
ファイル: sbasis-geometric.cpp プロジェクト: abrock/lib2geom
/** Return a function which gives the angle of vect at each point.
 \param vect a piecewise parameteric curve.
 \param tol the maximum error allowed.
 \param order the maximum degree to use for approximation
 \relates Piecewise
*/
Piecewise<SBasis>
Geom::atan2(Piecewise<D2<SBasis> > const &vect, double tol, unsigned order){
    Piecewise<SBasis> result;
    Piecewise<D2<SBasis> > v = cutAtRoots(vect,tol);
    result.cuts.push_back(v.cuts.front());
    for (unsigned i=0; i<v.size(); i++){

        D2<SBasis> vi = RescaleForNonVanishingEnds(v.segs[i]);
        SBasis x=vi[0], y=vi[1];
        Piecewise<SBasis> angle;
        angle = divide (x*derivative(y)-y*derivative(x), x*x+y*y, tol, order);

        //TODO: I don't understand this - sign.
        angle = integral(-angle);
        Point vi0 = vi.at0(); 
        angle += -std::atan2(vi0[1],vi0[0]) - angle[0].at0();
        //TODO: deal with 2*pi jumps form one seg to the other...
        //TODO: not exact at t=1 because of the integral.
        //TODO: force continuity?

        angle.setDomain(Interval(v.cuts[i],v.cuts[i+1]));
        result.concat(angle);   
    }
    return result;
}
コード例 #3
0
ファイル: sbasis-geometric.cpp プロジェクト: abrock/lib2geom
/** Reparameterise M to have unit speed.
 \param M the Element.
 \param tol the maximum error allowed.
 \param order the maximum degree to use for approximation
 \relates Piecewise, D2
*/
Piecewise<D2<SBasis> >
Geom::arc_length_parametrization(D2<SBasis> const &M,
                           unsigned order,
                           double tol){
    Piecewise<D2<SBasis> > u;
    u.push_cut(0);

    Piecewise<SBasis> s = arcLengthSb(Piecewise<D2<SBasis> >(M),tol);
    for (unsigned i=0; i < s.size();i++){
        double t0=s.cuts[i],t1=s.cuts[i+1];
        if ( are_near(s(t0),s(t1)) ) {
            continue;
        }
        D2<SBasis> sub_M = compose(M,Linear(t0,t1));
        D2<SBasis> sub_u;
        for (unsigned dim=0;dim<2;dim++){
            SBasis sub_s = s.segs[i];
            sub_s-=sub_s.at0();
            sub_s/=sub_s.at1();
            sub_u[dim]=compose_inverse(sub_M[dim],sub_s, order, tol);
        }
        u.push(sub_u,s(t1));
    }
    return u;
}
コード例 #4
0
ファイル: pw-funcs.cpp プロジェクト: mental/lib2geom
    virtual void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save) {
        cairo_set_source_rgba (cr, 0., 0., 0., 1);
        cairo_set_line_width (cr, 1);
        
        Piecewise<SBasis> pws;
        
        //pws = Geom::cos(Linear(0,100)) + 3;
        pws = Geom::sqrt(Linear(0,100));
        //pws = log(Interval(1,8));
        //Piecewise<SBasis> l(Linear(-100,100));
        //Piecewise<SBasis> one(Linear(1,1));
        //pws = Geom::reciprocal(l*l + one)*l + l;
        //pws = xlogx(Interval(0.5,3));
        //pws = Geom::reciprocal(pws);
        //pws = -integral(Geom::reciprocal(Linear(1,2)))*Piecewise<SBasis>(Linear(1,2));
        
        pws = -pws*width/4 + width/2;
        pws.scaleDomain(width/2);
        pws.offsetDomain(width/4);

        cairo_pw(cr, pws);

        cairo_stroke(cr);
        cairo_set_source_rgba (cr, 0., 0., .5, 1.);
        cairo_horiz(cr, 500, pws.cuts);
        cairo_stroke(cr);

        *notify << "total pieces: " << pws.size();

        Toy::draw(cr, notify, width, height, save);
    }
コード例 #5
0
ファイル: worms.cpp プロジェクト: mental/lib2geom
 void reverse_direction(int t) {
     path = portion(path, 0, t - last_time);
     D2<SBasis> seg = random_d2(), last = path[path.size()-1];
     for(unsigned c = 0; c < 2; c++)
         for(unsigned d = 1; d < seg[c].size() && d < last[c].size(); d++)
             seg[c][d][0] = -last[c][d][1];
     add_section(seg);
 }
コード例 #6
0
ファイル: center-warp.cpp プロジェクト: mental/lib2geom
void cairo_pw(cairo_t *cr, Piecewise<SBasis> p) {
    for(unsigned i = 0; i < p.size(); i++) {
        D2<SBasis> B;
        B[0] = Linear(p.cuts[i], p.cuts[i+1]);
        B[1] = p[i];
        cairo_d2_sb(cr, B);
    }
}
コード例 #7
0
ファイル: sb-to-bez.cpp プロジェクト: dov/lib2geom
void cairo_pw(cairo_t *cr, Piecewise<SBasis> p, double hscale=1., double vscale=1.) {
    for(unsigned i = 0; i < p.size(); i++) {
        D2<SBasis> B;
        B[0] = Linear(150+p.cuts[i]*hscale, 150+p.cuts[i+1]*hscale);
        B[1] = Linear(450) - p[i]*vscale;
        cairo_d2_sb(cr, B);
    }
}
コード例 #8
0
ファイル: sbasis-math.cpp プロジェクト: loveq369/DoonSketch
/** Compute the cosine of a function.
 \param f function
 \param tol maximum error
 \param order maximum degree polynomial to use
*/
Piecewise<SBasis> cos(Piecewise<SBasis> const &f, double tol, int order){
    Piecewise<SBasis> result;
    for (unsigned i=0; i<f.size(); i++){
        Piecewise<SBasis> cosfi = cos(f.segs[i],tol,order);
        cosfi.setDomain(Interval(f.cuts[i],f.cuts[i+1]));
        result.concat(cosfi);
    }
    return result;
}
コード例 #9
0
ファイル: sbasis-geometric.cpp プロジェクト: abrock/lib2geom
/** Calculates the length of a Piecewise<D2<SBasis> > through gsl integration.
 \param s the Element.
 \param tol the maximum error allowed.
 \relates Piecewise
If you only want the total length, this routine faster and more accurate than constructing an arcLengthSb.
*/
double
Geom::length(Piecewise<D2<SBasis> > const &s,
                 double tol){
    double result = 0;
    double abs_error = 0;
    for (unsigned i=0; i < s.size();i++){
        length_integrating(s[i], result, abs_error, tol);
    }
    return result;
}
コード例 #10
0
ファイル: sbasis-geometric.cpp プロジェクト: abrock/lib2geom
/** Reparameterise M to have unit speed.
 \param M the Element.
 \param tol the maximum error allowed.
 \param order the maximum degree to use for approximation
 \relates Piecewise
*/
Piecewise<D2<SBasis> >
Geom::arc_length_parametrization(Piecewise<D2<SBasis> > const &M,
                                 unsigned order,
                                 double tol){
    Piecewise<D2<SBasis> > result;
    for (unsigned i=0; i<M.size(); i++) {
        result.concat( arc_length_parametrization(M[i],order,tol) );
    }
    return result;
}
コード例 #11
0
ファイル: sbasis-geometric.cpp プロジェクト: abrock/lib2geom
/** returns a function giving the curvature at each point in M.
 \param M the Element.
 \param tol the maximum error allowed.
 \relates Piecewise
 \todo claimed incomplete.  Check.
*/
Piecewise<SBasis> 
Geom::curvature(Piecewise<D2<SBasis> > const &V, double tol){
    Piecewise<SBasis> result;
    Piecewise<D2<SBasis> > VV = cutAtRoots(V);
    result.cuts.push_back(VV.cuts.front());
    for (unsigned i=0; i<VV.size(); i++){
        Piecewise<SBasis> curv_seg;
        curv_seg = curvature(VV.segs[i],tol);
        curv_seg.setDomain(Interval(VV.cuts[i],VV.cuts[i+1]));
        result.concat(curv_seg);
    }
    return result;
}
コード例 #12
0
ファイル: sbasis-geometric.cpp プロジェクト: abrock/lib2geom
/** Return a Piecewise<D2<SBasis> > which points in the same direction as V_in, but has unit_length.
 \param V_in the original path.
 \param tol the maximum error allowed.
 \param order the maximum degree to use for approximation

unitVector(x,y) is computed as (b,-a) where a and b are solutions of:
     ax+by=0 (eqn1)   and   a^2+b^2=1 (eqn2)

 \relates Piecewise
*/
Piecewise<D2<SBasis> >
Geom::unitVector(Piecewise<D2<SBasis> > const &V, double tol, unsigned order){
    Piecewise<D2<SBasis> > result;
    Piecewise<D2<SBasis> > VV = cutAtRoots(V);
    result.cuts.push_back(VV.cuts.front());
    for (unsigned i=0; i<VV.size(); i++){
        Piecewise<D2<SBasis> > unit_seg;
        unit_seg = unitVector(VV.segs[i],tol, order);
        unit_seg.setDomain(Interval(VV.cuts[i],VV.cuts[i+1]));
        result.concat(unit_seg);   
    }
    return result;
}
コード例 #13
0
ファイル: 2dsb2d.cpp プロジェクト: abrock/lib2geom
    void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
        Geom::Point dir(1,-2);
        for(unsigned dim = 0; dim < 2; dim++) {
            Geom::Point dir(0,0);
            dir[dim] = 1;
            for(unsigned vi = 0; vi < sb2[dim].vs; vi++)
                for(unsigned ui = 0; ui < sb2[dim].us; ui++)
                    for(unsigned iv = 0; iv < 2; iv++)
                        for(unsigned iu = 0; iu < 2; iu++) {
                            unsigned corner = iu + 2*iv;
                            unsigned i = ui + vi*sb2[dim].us;
                            Geom::Point base((2*(iu+ui)/(2.*ui+1)+1)*width/4.,
                                             (2*(iv+vi)/(2.*vi+1)+1)*width/4.);
                            if(vi == 0 && ui == 0) {
                                base = Geom::Point(width/4., width/4.);
                            }
                            double dl = dot((hand.pts[corner+4*i] - base), dir)/dot(dir,dir);
                            sb2[dim][i][corner] = dl/(width/2)*pow(4.0,(double)ui+vi);
                        }
        }
        cairo_d2_sb2d(cr, sb2, dir*0.1, width);
        cairo_set_source_rgba (cr, 0., 0., 0, 0.5);
        cairo_stroke(cr);
        for(unsigned i = 0; i < path_a_pw.size(); i++) {
            D2<SBasis> B = path_a_pw[i];
            //const int depth = sb2[0].us*sb2[0].vs;
            //const int surface_hand.pts = 4*depth;
            //D2<SBasis> B = hand.pts_to_sbasis<3>(hand.pts.begin() + surface_hand.pts);
            cairo_d2_sb(cr, B);
            for(unsigned dim = 0; dim < 2; dim++) {
                std::vector<double> r = roots(B[dim]);
                for(unsigned i = 0; i < r.size(); i++)
                    draw_cross(cr, B(r[i]));
                r = roots(Linear(width/4) - B[dim]);
                for(unsigned i = 0; i < r.size(); i++)
                    draw_cross(cr, B(r[i]));
            }
            cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
            cairo_stroke(cr);
            B *= (4./width);
            D2<SBasis> tB = compose_each(sb2, B);
            B = B*(width/2) + Geom::Point(width/4, width/4);
            tB = tB*(width/2) + Geom::Point(width/4, width/4);
            
            cairo_d2_sb(cr, tB);
        }
        
        //*notify << "bo = " << sb2.index(0,0);

        Toy::draw(cr, notify, width, height, save,timer_stream);
    }
コード例 #14
0
ファイル: sbasis-geometric.cpp プロジェクト: abrock/lib2geom
//=================================================================
//TODO: what's this for?!?!
Piecewise<D2<SBasis> > 
Geom::cutAtRoots(Piecewise<D2<SBasis> > const &M, double ZERO){
    vector<double> rts;
    for (unsigned i=0; i<M.size(); i++){
        vector<double> seg_rts = roots((M.segs[i])[0]);
        seg_rts = vect_intersect(seg_rts, roots((M.segs[i])[1]), ZERO);
        Linear mapToDom = Linear(M.cuts[i],M.cuts[i+1]);
        for (unsigned r=0; r<seg_rts.size(); r++){
            seg_rts[r]= mapToDom(seg_rts[r]);
        }
        rts.insert(rts.end(),seg_rts.begin(),seg_rts.end());
    }
    return partition(M,rts);
}
コード例 #15
0
ファイル: sbasis-geometric.cpp プロジェクト: abrock/lib2geom
/**
 * Centroid using sbasis integration.
 \param p the Element.
 \param centroid on return contains the centroid of the shape
 \param area on return contains the signed area of the shape.
 \relates Piecewise
This approach uses green's theorem to compute the area and centroid using integrals.  For curved shapes this is much faster than converting to polyline.  Note that without an uncross operation the output is not the absolute area.

 * Returned values: 
    0 for normal execution;
    2 if area is zero, meaning centroid is meaningless.

 */
unsigned Geom::centroid(Piecewise<D2<SBasis> > const &p, Point& centroid, double &area) {
    Point centroid_tmp(0,0);
    double atmp = 0;
    for(unsigned i = 0; i < p.size(); i++) {
        SBasis curl = dot(p[i], rot90(derivative(p[i])));
        SBasis A = integral(curl);
        D2<SBasis> C = integral(multiply(curl, p[i]));
        atmp += A.at1() - A.at0();
        centroid_tmp += C.at1()- C.at0(); // first moment.
    }
// join ends
    centroid_tmp *= 2;
    Point final = p[p.size()-1].at1(), initial = p[0].at0();
    const double ai = cross(final, initial);
    atmp += ai;
    centroid_tmp += (final + initial)*ai; // first moment.
    
    area = atmp / 2;
    if (atmp != 0) {
        centroid = centroid_tmp / (3 * atmp);
        return 0;
    }
    return 2;
}
コード例 #16
0
ファイル: minsb2d-solver.cpp プロジェクト: dov/lib2geom
void
plot3d(cairo_t *cr, 
       Piecewise<SBasis> const &x, 
       Piecewise<SBasis> const &y, 
       Piecewise<SBasis> const &z, Frame frame){
    
    Piecewise<SBasis> xx = partition(x,y.cuts);
    Piecewise<SBasis> xxx = partition(xx,z.cuts);
    Piecewise<SBasis> yyy = partition(y,xxx.cuts);
    Piecewise<SBasis> zzz = partition(z,xxx.cuts);
    
    for (unsigned i=0; i<xxx.size(); i++){
        plot3d(cr, xxx[i], yyy[i], zzz[i], frame);
    }
}
コード例 #17
0
ファイル: sb-math-test.cpp プロジェクト: mental/lib2geom
static void plot(cairo_t* cr, Piecewise<SBasis> const &f,double vscale=1){
    D2<Piecewise<SBasis> > plot;
    plot[1]=-f;
    plot[1]*=vscale;
    plot[1]+=300;
    
    plot[0].cuts.push_back(f.cuts.front());
    plot[0].cuts.push_back(f.cuts.back());
    plot[0].segs.push_back(Linear(150,450));

    cairo_d2_pw_sb(cr, plot);

    for (unsigned i=1; i<f.size(); i++){
        cairo_move_to(cr, Point(150+f.cuts[i]*300,300));
        cairo_line_to(cr, Point(150+f.cuts[i]*300,300-vscale*f.segs[i].at0()));
    }
}
コード例 #18
0
ファイル: center-warp.cpp プロジェクト: mental/lib2geom
    void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save) {
        Geom::Point dir(1,-2);

	D2<Piecewise<SBasis> > B = make_cuts_independent(path_a_pw);

	cairo_set_source_rgba (cr, 0., 0.125, 0, 1);

        if(0) {
            D2<Piecewise<SBasis> > tB(cos(B[0]*0.1)*(brush_handle.pos[0]/100) + B[0], 
                                      cos(B[1]*0.1)*(brush_handle.pos[1]/100) + B[1]);
	
            cairo_d2_pw_sb(cr, tB);
        } else  {
            Piecewise<SBasis> r2 = (dot(path_a_pw - brush_handle.pos, path_a_pw - brush_handle.pos));
            Piecewise<SBasis> rc;
            rc.push_cut(0);
            rc.push(SBasis(Linear(1, 1)), 2);
            rc.push(SBasis(Linear(1, 0)), 4);
            rc.push(SBasis(Linear(0, 0)), 30);
            rc *= 10;
            rc.scaleDomain(1000);
            Piecewise<SBasis> swr;
            swr.push_cut(0);
            swr.push(SBasis(Linear(0, 1)), 2);
            swr.push(SBasis(Linear(1, 0)), 4);
            swr.push(SBasis(Linear(0, 0)), 30);
            swr *= 10;
            swr.scaleDomain(1000);
            cairo_pw(cr, swr);// + (height - 100));
            D2<Piecewise<SBasis> >  uB = make_cuts_independent(unitVector(path_a_pw - brush_handle.pos));
        
            D2<Piecewise<SBasis> > tB(compose(rc, (r2))*uB[0] + B[0], 
                                      compose(rc, (r2))*uB[1] + B[1]);
            cairo_d2_pw_sb(cr, tB);
            //path_a_pw = sectionize(tB);
	}
	cairo_stroke(cr);
        
        *notify << path_a_pw.size();
        
        Toy::draw(cr, notify, width, height, save);
    }
コード例 #19
0
ファイル: inverse-test.cpp プロジェクト: dov/lib2geom
static void plot(cairo_t* cr, Piecewise<SBasis> const &f,double vscale=1){
  for (unsigned i=0;i<f.size();i++){
      plot(cr,f.segs[i],vscale,f.cuts[i],f.cuts[i+1]);
      draw_cross(cr,Geom::Point(f.cuts[i]*300 + 150, f.segs[i][0][0]*(-vscale) + 450));
  }
}