Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

fit.C

Go to the documentation of this file.
00001 /**********************************************************************
00002  * fit.C:
00003  *
00004  *      Read a mesh from stdin (.sm format).
00005  *
00006  *      Treating it as the control mesh for a loop subdivision
00007  *      surface, compute new control point positions so that the limit
00008  *      location of each new control point exactly equals the original
00009  *      control point position. (Well, very nearly).
00010  *
00011  *      Write the result to stdout.
00012  *
00013  *      The default is to use Jacobi iteration. To select Gauss-Seidel
00014  *      iteration with -g flag. (For a description of these iterations
00015  *      see: G. H. Golub and C. F. van Loan. Matrtix Computations, 3rd
00016  *      Edition. Section 10.1.1, page 510.)
00017  **********************************************************************/
00018 #include "std/stop_watch.H"
00019 #include "mi.H"
00020 #include "lmesh.H"
00021 
00022 void
00023 fit(LMESHptr& mesh, bool do_gauss_seidel)
00024 {
00025    if (mesh->empty())
00026       return;
00027 
00028    // time this
00029    stop_watch clock;
00030 
00031    double max_err = mesh->get_bb().dim().length() * 1e-5;
00032    int n = mesh->nverts();
00033 
00034    // get original control point locations
00035    Wpt_list C(n);   // original control points
00036    Wpt_list L(n);   // current limit points
00037    for (int i=0; i<n; i++) {
00038       C += mesh->bv(i)->loc();
00039       L += Wpt::Origin();
00040    }
00041 
00042    // do 50 iterations...
00043    double prev_err = 0;
00044    for (int k=0; k<50; k++) {
00045       double err = 0;
00046       if (do_gauss_seidel) {
00047          // Gauss-Seidel iteration: use updated values from the
00048          // current iteration as they are computed...
00049          for (int j=0; j<n; j++) {
00050             // don't need that L[] array...
00051             Wpt limit;
00052             mesh->lv(j)->limit_loc(limit);
00053             Wvec delt = C[j] - limit;
00054             err += delt.length();
00055             mesh->bv(j)->offset_loc(delt);
00056          }
00057       } else {
00058          // compute the new offsets from the offsets computed in the
00059          // previous iteration
00060          int j;
00061          for (j=0; j<n; j++)
00062             mesh->lv(j)->limit_loc(L[j]);
00063          for (j=0; j<n; j++) {
00064             Wvec delt = C[j] - L[j];
00065             err += delt.length();
00066             mesh->bv(j)->offset_loc(delt);
00067 
00068          }
00069       }
00070       // compute the average error:
00071       err /= n;
00072       if (prev_err != 0) {
00073          err_msg("Iter %d: avg error: %f, reduction: %f",
00074                  k, err, err/prev_err);
00075       } else {
00076          err_msg("Iter %d: avg error: %f", k, err);
00077       }
00078       prev_err = err;
00079       if (err < max_err)
00080          break;
00081    }
00082 
00083    err_msg("fitting took %.2f seconds", clock.elapsed_time());
00084 }
00085 
00086 int 
00087 main(int argc, char *argv[])
00088 {
00089    bool do_gauss_seidel = 0;
00090 
00091    if (argc == 2 && str_ptr(argv[1]) == str_ptr("-g"))
00092       do_gauss_seidel = 1;
00093    else if(argc != 1)
00094    {
00095       err_msg("Usage: %s [ -g ] < mesh.sm > mesh-fit.sm", argv[0]);
00096       return 1;
00097    }
00098 
00099    LMESHptr mesh = LMESH::read_jot_stream(cin);
00100    if (!mesh || mesh->empty())
00101       return 1; // didn't work
00102 
00103    fit(mesh, do_gauss_seidel);
00104 
00105    mesh->write_stream(cout);
00106 
00107    return 0;
00108 }
00109 
00110 /* end of file fit.C */

Generated on Mon Sep 18 11:39:29 2006 for jot by  doxygen 1.4.4