Пример #1
0
 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
/** 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
/** 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
    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
 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
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
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
/** 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
/** 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
/** 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
/** 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
/** 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
    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
//=================================================================
//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
/**
 * 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
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
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
    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
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));
  }
}