/**
 * Finds a path which traces the 0 contour of f, traversing from A to B as a single d2<sbasis>.
 * degmax specifies the degree (degree = 2*degmax-1, so a degmax of 2 generates a cubic fit).
 * The algorithm is based on dividing out derivatives at each end point and does not use the curvature for fitting.
 * It is less accurate than sb2d_cubic_solve, although this may be fixed in the future. 
 */
D2<SBasis>
sb2dsolve(SBasis2d const &f, Geom::Point const &A, Geom::Point const &B, unsigned degmax){
    //g_warning("check f(A)= %f = f(B) = %f =0!", f.apply(A[X],A[Y]), f.apply(B[X],B[Y]));

    SBasis2d dfdu = partial_derivative(f, 0);
    SBasis2d dfdv = partial_derivative(f, 1);
    Geom::Point dfA(dfdu.apply(A[X],A[Y]),dfdv.apply(A[X],A[Y]));
    Geom::Point dfB(dfdu.apply(B[X],B[Y]),dfdv.apply(B[X],B[Y]));
    Geom::Point nA = dfA/(dfA[X]*dfA[X]+dfA[Y]*dfA[Y]);
    Geom::Point nB = dfB/(dfB[X]*dfB[X]+dfB[Y]*dfB[Y]);

    D2<SBasis>result(SBasis(degmax, Linear()), SBasis(degmax, Linear()));
    double fact_k=1;
    double sign = 1.;
    for(int dim = 0; dim < 2; dim++)
        result[dim][0] = Linear(A[dim],B[dim]);
    for(unsigned k=1; k<degmax; k++){
        // these two lines make the solutions worse!
        //fact_k *= k;
        //sign = -sign;
        SBasis f_on_curve = compose(f,result);
        Linear reste = f_on_curve[k];
        double ax = -reste[0]/fact_k*nA[X];
        double ay = -reste[0]/fact_k*nA[Y];
        double bx = -sign*reste[1]/fact_k*nB[X];
        double by = -sign*reste[1]/fact_k*nB[Y];

        result[X][k] = Linear(ax,bx);
        result[Y][k] = Linear(ay,by);
        //sign *= 3;
    }    
    return result;
}
SBasis2d partial_derivative(SBasis2d const &f, int dim) {
    SBasis2d result;
    for(unsigned i = 0; i < f.size(); i++) {
        result.push_back(Linear2d(0,0,0,0));
    }
    result.us = f.us;
    result.vs = f.vs;

    for(unsigned i = 0; i < f.us; i++) {
        for(unsigned j = 0; j < f.vs; j++) {
            Linear2d lin = f.index(i,j);
            Linear2d dlin(lin[1+dim]-lin[0], lin[1+2*dim]-lin[dim], lin[3-dim]-lin[2*(1-dim)], lin[3]-lin[2-dim]);
            result[i+j*result.us] += dlin;
            unsigned di = dim?j:i;
            if (di>=1){
                float motpi = dim?-1:1;
                Linear2d ds_lin_low( lin[0], -motpi*lin[1], motpi*lin[2], -lin[3] );
                result[(i+dim-1)+(j-dim)*result.us] += di*ds_lin_low;
                
                Linear2d ds_lin_hi( lin[1+dim]-lin[0], lin[1+2*dim]-lin[dim], lin[3]-lin[2-dim], lin[3-dim]-lin[2-dim] );
                result[i+j*result.us] += di*ds_lin_hi;                
            }
        }
    }
    return result;
}
Exemple #3
0
void
v_coef(SBasis2d f, unsigned deg, SBasis &a, SBasis &b) {
    a = SBasis(f.us, Linear());
    b = SBasis(f.us, Linear());
    for (unsigned u=0; u<f.us; u++){
        a[u] = Linear(f.index(deg,u)[0], f.index(deg,u)[1]);
        b[u] = Linear(f.index(deg,u)[2], f.index(deg,u)[3]);
    }
}
Exemple #4
0
//see a sb2d as an sb of u with coef in sbasis of v.
void
u_coef(SBasis2d f, unsigned deg, SBasis &a, SBasis &b) {
    a = SBasis(f.vs, Linear());
    b = SBasis(f.vs, Linear());
    for (unsigned v=0; v<f.vs; v++){
        a[v] = Linear(f.index(deg,v)[0], f.index(deg,v)[2]);
        b[v] = Linear(f.index(deg,v)[1], f.index(deg,v)[3]);
    }
}
Exemple #5
0
void
v_coef(SBasis2d f, unsigned deg, SBasis &a, SBasis &b) {
    a = SBasis();
    b = SBasis();
    for (unsigned u=0; u<f.us; u++){
        a.push_back(Linear(f.index(deg,u)[0], f.index(deg,u)[1]));
        b.push_back(Linear(f.index(deg,u)[2], f.index(deg,u)[3]));
    }
}
Exemple #6
0
//see a sb2d as an sb of u with coef in sbasis of v.
void
u_coef(SBasis2d f, unsigned deg, SBasis &a, SBasis &b) {
    a = SBasis();
    b = SBasis();
    for (unsigned v=0; v<f.vs; v++){
        a.push_back(Linear(f.index(deg,v)[0], f.index(deg,v)[2]));
        b.push_back(Linear(f.index(deg,v)[1], f.index(deg,v)[3]));
    }
}
SBasis extract_u(SBasis2d const &a, double u) {
    SBasis sb(a.vs, Linear());
    double s = u*(1-u);
    
    for(unsigned vi = 0; vi < a.vs; vi++) {
        double sk = 1;
        Linear bo(0,0);
        for(unsigned ui = 0; ui < a.us; ui++) {
            bo += (extract_u(a.index(ui, vi), u))*sk;
            sk *= s;
        }
        sb[vi] = bo;
    }
    
    return sb;
}
SBasis extract_v(SBasis2d const &a, double v) {
    SBasis sb(a.us, Linear());
    double s = v*(1-v);
    
    for(unsigned ui = 0; ui < a.us; ui++) {
        double sk = 1;
        Linear bo(0,0);
        for(unsigned vi = 0; vi < a.vs; vi++) {
            bo += (extract_v(a.index(ui, vi), v))*sk;
            sk *= s;
        }
        sb[ui] = bo;
    }
    
    return sb;
}
Exemple #9
0
    virtual void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {

        double slider_top = width/4.;
        double slider_bot = width*3./4.;
        double slider_margin = width/8.;
        if(hand.pts.empty()) {
            hand.pts.push_back(Geom::Point(width*3./16., 3*width/4.));
            hand.pts.push_back(hand.pts[0] + Geom::Point(width/2., 0));
            hand.pts.push_back(hand.pts[0] + Geom::Point(width/8., -width/12.));
            hand.pts.push_back(hand.pts[0] + Geom::Point(0,-width/4.));
            hand.pts.push_back(Geom::Point(slider_margin,slider_bot));
            hand.pts.push_back(Geom::Point(width-slider_margin,slider_top));
        }
        
        hand.pts[4][X] = slider_margin;
        if (hand.pts[4][Y]<slider_top) hand.pts[4][Y] = slider_top; 
        if (hand.pts[4][Y]>slider_bot) hand.pts[4][Y] = slider_bot; 
        hand.pts[5][X] = width-slider_margin;
        if (hand.pts[5][Y]<slider_top) hand.pts[5][Y] = slider_top; 
        if (hand.pts[5][Y]>slider_bot) hand.pts[5][Y] = slider_bot; 

        double tA = (slider_bot-hand.pts[4][Y])/(slider_bot-slider_top);
        double tB = (slider_bot-hand.pts[5][Y])/(slider_bot-slider_top);

        cairo_move_to(cr,Geom::Point(slider_margin,slider_bot));
        cairo_line_to(cr,Geom::Point(slider_margin,slider_top));
        cairo_move_to(cr,Geom::Point(width-slider_margin,slider_bot));
        cairo_line_to(cr,Geom::Point(width-slider_margin,slider_top));
        cairo_set_line_width(cr,.5);
        cairo_set_source_rgba (cr, 0., 0.3, 0., 1.);
        cairo_stroke(cr);
        
        Frame frame;
        frame.O = hand.pts[0];//
        frame.x = hand.pts[1]-hand.pts[0];//
        frame.y = hand.pts[2]-hand.pts[0];//
        frame.z = hand.pts[3]-hand.pts[0];// 

/*
        SBasis2d f = y_x2();
        D2<SBasis> true_solution(Linear(0,1),Linear(0,1));
        true_solution[Y].push_back(Linear(-1,-1));
        SBasis zero = SBasis(Linear(0.));
        Geom::Point A = true_solution(tA);
        Geom::Point B = true_solution(tB);
*/

        SBasis2d f = x2_plus_y2_1();
        D2<Piecewise<SBasis> > true_solution;
        true_solution[X] = cos(SBasis(Linear(0,3.141592/2)));
        true_solution[Y] = sin(SBasis(Linear(0,3.141592/2)));
        Piecewise<SBasis> zero = Piecewise<SBasis>(SBasis(Linear(0.)));
        //Geom::Point A(cos(tA*M_PI/2), sin(tA*M_PI/2));// = true_solution(tA);
        //Geom::Point B(cos(tB*M_PI/2), sin(tB*M_PI/2));// = true_solution(tB);
        Geom::Point A = true_solution(tA);
        Geom::Point B = true_solution(tB);
        Point dA(-sin(tA*M_PI/2), cos(tA*M_PI/2));
        Geom::Point dB(-sin(tB*M_PI/2), cos(tB*M_PI/2));
        SBasis2d dfdu = partial_derivative(f, 0);
        SBasis2d dfdv = partial_derivative(f, 1);
        Geom::Point dfA(dfdu.apply(A[X],A[Y]),dfdv.apply(A[X],A[Y]));
        Geom::Point dfB(dfdu.apply(B[X],B[Y]),dfdv.apply(B[X],B[Y]));
        dA = rot90(dfA);
        dB = rot90(dfB);

        plot3d(cr,Linear(0,1),Linear(0,0),Linear(0,0),frame);
        plot3d(cr,Linear(0,1),Linear(1,1),Linear(0,0),frame);
        plot3d(cr,Linear(0,0),Linear(0,1),Linear(0,0),frame);
        plot3d(cr,Linear(1,1),Linear(0,1),Linear(0,0),frame);
        cairo_set_line_width(cr,.2);
        cairo_set_source_rgba (cr, 0., 0., 0., 1.);
        cairo_stroke(cr);

        plot3d_top(cr,f,frame);
        cairo_set_line_width(cr,1);        
        cairo_set_source_rgba (cr, .5, 0.5, 0.5, 1.);
        cairo_stroke(cr);
        plot3d(cr,f,frame);
        cairo_set_line_width(cr,.2);        
        cairo_set_source_rgba (cr, .5, 0.5, 0.5, 1.);
        cairo_stroke(cr);

        plot3d(cr, true_solution[X], true_solution[Y], zero, frame);
        cairo_set_line_width(cr,.5);
        cairo_set_source_rgba (cr, 0., 0., 0., 1.);
        cairo_stroke(cr);
        double error;
        for(int degree = 2; degree < 2; degree++) {
            D2<SBasis> zeroset = sb2dsolve(f,A,B,degree);
            plot3d(cr, zeroset[X], zeroset[Y], SBasis(Linear(0.)),frame);
            cairo_set_line_width(cr,1);        
            cairo_set_source_rgba (cr, 0.9, 0., 0., 1.);
            cairo_stroke(cr);
            
            SBasis comp = compose(f,zeroset);
            plot3d(cr, zeroset[X], zeroset[Y], comp, frame);
            cairo_set_source_rgba (cr, 0.7, 0., 0.7, 1.);
            cairo_stroke(cr);
            //Fix Me: bounds_exact does not work here?!?!
            Interval bounds = *bounds_fast(comp);
            error = (bounds.max()>-bounds.min() ? bounds.max() : -bounds.min() );
        }
        if (1) {

            bits_n_bobs par = {&f, A, B, dA, dB};
            bits_n_bobs* bnb = &par;
            std::cout << f[0] << "= intial f \n";
            const gsl_multimin_fminimizer_type *T = 
                gsl_multimin_fminimizer_nmsimplex;
            gsl_multimin_fminimizer *s = NULL;
            gsl_vector *ss, *x;
            gsl_multimin_function minex_func;
     
            size_t iter = 0;
            int status;
            double size;
     
            /* Starting point */
            x = gsl_vector_alloc (2);
            gsl_vector_set (x, 0, 0.552); // magic number for quarter circle
            gsl_vector_set (x, 1, 0.552);
     
            /* Set initial step sizes to 1 */
            ss = gsl_vector_alloc (2);
            gsl_vector_set_all (ss, 0.1);
     
            /* Initialize method and iterate */
            minex_func.n = 2;
            minex_func.f = &my_f;
            minex_func.params = (void *)&par;
     
            s = gsl_multimin_fminimizer_alloc (T, 2);
            gsl_multimin_fminimizer_set (s, &minex_func, x, ss);
     
            do
            {
                iter++;
                status = gsl_multimin_fminimizer_iterate(s);
           
                if (status) 
                    break;
     
                size = gsl_multimin_fminimizer_size (s);
                status = gsl_multimin_test_size (size, 1e-7);
     
                if (status == GSL_SUCCESS)
                {
                    printf ("converged to minimum at\n");
                }
     
            }
            while (status == GSL_CONTINUE && iter < 100);
            printf ("%5lu %g %gf f() = %g size = %g\n", 
                    iter,
                    gsl_vector_get (s->x, 0), 
                    gsl_vector_get (s->x, 1), 
                    s->fval, size);
            {
                double x = gsl_vector_get(s->x, 0);
                double y = gsl_vector_get(s->x, 1);
                Bezier b0(bnb->B[0], bnb->B[0]+bnb->dB[0]*x, bnb->A[0]+bnb->dA[0]*y, bnb->A[0]);
                Bezier b1(bnb->B[1], bnb->B[1]+bnb->dB[1]*x, bnb->A[1]+bnb->dA[1]*y, bnb->A[1]);
            
                D2<SBasis> zeroset(b0.toSBasis(), b1.toSBasis());
                plot3d(cr, zeroset[X], zeroset[Y], SBasis(Linear(0.)),frame);
                cairo_set_line_width(cr,1);        
                cairo_set_source_rgba (cr, 0.9, 0., 0., 1.);
                cairo_stroke(cr);
            
                SBasis comp = compose(f,zeroset);
                plot3d(cr, zeroset[X], zeroset[Y], comp, frame);
                cairo_set_source_rgba (cr, 0.7, 0., 0.7, 1.);
                cairo_stroke(cr);
                //Fix Me: bounds_exact does not work here?!?!
                Interval bounds = *bounds_fast(comp);
                error = (bounds.max()>-bounds.min() ? bounds.max() : -bounds.min() );

            }        
       
            gsl_vector_free(x);
            gsl_vector_free(ss);
            gsl_multimin_fminimizer_free (s);
        }
        *notify << "Gray: f-graph and true solution,\n";
        *notify << "Red: solver solution,\n";
        *notify << "Purple: value of f over solver solution.\n";
        *notify << "  error: "<< error <<".\n";
        
        Toy::draw(cr, notify, width, height, save,timer_stream);
    }