CyberScan.cc
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:36k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. //############################################################
  2. // 
  3. // CyberScan.cc
  4. //
  5. // Kari Pulli
  6. // Wed Jul  8 13:15:25 PDT 1998
  7. //
  8. // Store range scan information from a Cyberware custom made
  9. // range scanner for the Digital Michelangelo project.
  10. //
  11. //############################################################
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include "DirEntries.h"
  15. #include <fstream.h>
  16. #ifdef WIN32
  17. # include <float.h>
  18. #endif
  19. #ifdef sgi
  20. # include <ieeefp.h>
  21. #endif
  22. #ifdef linux
  23. #       define MAXFLOAT FLT_MAX
  24. #endif
  25. #include "CyberScan.h"
  26. #include "plvGlobals.h"
  27. #include "plvDraw.h"
  28. #include "KDindtree.h"
  29. #include "Random.h"
  30. #include "TriMeshUtils.h"
  31. #include "defines.h"
  32. #include "FileNameUtils.h"
  33. #include "Bbox.h"
  34. #include "Progress.h"
  35. #include "BailDetector.h"
  36. #include "ColorUtils.h"
  37. #include "algo.h"
  38. #include "MeshTransport.h"
  39. #include "VertexFilter.h"
  40. #define SUBSAMPS 7
  41. static ColorSet _cset;
  42. KDindtree*
  43. CyberScan::get_current_kdtree()
  44. {
  45.   int iTree = current_resolution_index();
  46.   assert (iTree < kdtree.size());
  47.   if (kdtree[iTree] != NULL)
  48.     return kdtree[iTree];
  49.   regLevelData* level = getCurrentRegLevel();
  50.   kdtree[iTree] = CreateKDindtree(level->pnts->begin(), 
  51.   level->nrms->begin(),
  52.   level->pnts->size());
  53.   return kdtree[iTree];
  54. }
  55. void
  56. CyberScan::read_postprocess(const char *filename)
  57. {
  58.   for (int i = 0; i < SUBSAMPS; i++) {
  59.     char name[PATH_MAX];
  60.     strcpy (name, filename);
  61.     char* ext = strrchr (name, '.');
  62.     if (ext == NULL)
  63.       ext = name + strlen (name);
  64.     sprintf (ext, "_samp%d.ply", 1<<i);
  65.     int nFacesEstimated = 0;
  66.     for (int j = 0; j < sweeps.size(); j++) {
  67.       nFacesEstimated += sweeps[j]->resolutions[i].abs_resolution;
  68.     }
  69.     insert_resolution(nFacesEstimated, name, false, false);
  70.     kdtree.push_back (NULL);
  71.     reglevels.push_back (NULL);
  72.   }
  73.   // by default, start at lowest res
  74.   for (i=0; i<sweeps.size(); i++) 
  75.     sweeps[i]->select_coarsest();
  76.   select_coarsest();
  77.   // fill holes if requested
  78.   if (!strcmp(Tcl_GetVar(g_tclInterp, "subsamplePreserveHoles",
  79.                  TCL_GLOBAL_ONLY), "filter")) {
  80. for (i=0; i<sweeps.size(); i++) {
  81.   sweeps[i]->sd.fill_holes(2, 30);
  82.   sweeps[i]->sd.fill_holes(1, 20);
  83. }
  84.   }
  85. }
  86. CyberScan::CyberScan()
  87. {
  88.   bDirty = false;
  89. }
  90. CyberScan::~CyberScan ()
  91. {
  92.   while (reglevels.size()) {
  93.     delete reglevels.back();
  94.     reglevels.pop_back();
  95.   }
  96.   while (sweeps.size()) {
  97.     delete sweeps.back();
  98.     sweeps.pop_back();
  99.   }
  100.   while (kdtree.size()) {
  101.     delete kdtree.back();
  102.     kdtree.pop_back();
  103.   }
  104. }
  105. MeshTransport*
  106. CyberScan::mesh(bool perVertex, bool stripped,
  107. ColorSource color, int colorSize)
  108. {
  109.   if (stripped && !perVertex) {
  110.     cerr << "No t-strips without per-vertex properties";
  111.     return NULL;
  112.   }
  113.   /* kberg - trying to get per face flat shading working
  114.   if (!perVertex) {
  115.     cerr << "No per face normals for CyberScan" << endl;
  116.     return NULL;
  117.   } 
  118.   */
  119.   
  120.   int i = current_resolution_index();
  121.   load_resolution (i);
  122.   MeshTransport *mt = new MeshTransport;
  123.   for (int iTurn = 0; iTurn < sweeps.size(); iTurn++) {
  124.     MeshTransport* turn = sweeps[iTurn]->mesh (perVertex, stripped, color, 
  125.        colorSize);
  126.     if (turn) {
  127.       mt->appendMT (turn, sweeps[iTurn]->getXform());
  128.       delete turn;
  129.     }
  130.   }
  131.   return mt;
  132. }
  133. int
  134. CyberScan::num_vertices(void)
  135. {
  136.   return getCurrentRegLevel()->pnts->size();
  137. }
  138. regLevelData*
  139. CyberScan::getHighestRegLevel (void)
  140. {
  141.   if (!resolutions[0].in_memory)
  142.     load_resolution (0);
  143.   return getRegLevelFor (0);
  144. }
  145. regLevelData*
  146. CyberScan::getCurrentRegLevel (void)
  147. {
  148.   return getRegLevelFor (current_resolution_index());
  149. }
  150. regLevelData*
  151. CyberScan::getRegLevelFor (int iRes)
  152. {
  153.   assert (iRes < reglevels.size());
  154.   load_resolution (iRes);
  155.   assert (resolutions[iRes].in_memory);
  156.   if (!reglevels[iRes]) {
  157.     regLevelData* rl = reglevels[iRes] = new regLevelData;
  158.     if (sweeps.size() == 1) {
  159.       // don't actually need merge, so don't copy -- just share
  160.       rl->pnts = &sweeps[0]->levels[iRes]->pnts;
  161.       rl->nrms = &sweeps[0]->levels[iRes]->nrms;
  162.       rl->bdry = &sweeps[0]->levels[iRes]->bdry;
  163.       rl->bFree = false;
  164.     } else {
  165.       // need to create merged copy
  166.       // preallocate vectors
  167.       int nPts = 0;
  168.       for (int i = 0; i < sweeps.size(); i++) {
  169. nPts += sweeps[i]->levels[iRes]->pnts.size();
  170.       }
  171.       cout << "Merging sweep data (" << nPts
  172.    << " pts) for KDtree... " << flush;
  173.       rl->pnts = new vector<Pnt3>;  rl->pnts->reserve (nPts);
  174.       rl->nrms = new vector<short>; rl->nrms->reserve (nPts);
  175.       rl->bdry = new vector<char>;  rl->bdry->reserve (nPts);
  176.       rl->bFree = true;
  177.       
  178.       for (i = 0; i < sweeps.size(); i++) {
  179. levelData *ld = sweeps[i]->levels[iRes];
  180. long ps = rl->pnts->size();
  181. long ns = rl->nrms->size();
  182. rl->pnts->insert (rl->pnts->end(), 
  183.   ld->pnts.begin(), ld->pnts.end());
  184. rl->nrms->insert (rl->nrms->end(), 
  185.   ld->nrms.begin(), ld->nrms.end());
  186. rl->bdry->insert (rl->bdry->end(), 
  187.   ld->bdry.begin(), ld->bdry.end());
  188. Xform<float> sxf = sweeps[i]->getXform();
  189. if (!sxf.isIdentity()) {
  190.   // need to apply sweep's transform to the new data
  191.   for_each (rl->pnts->begin() + ps, rl->pnts->end(), sxf);
  192.   sxf.removeTranslation();
  193.   for (short* nb = rl->nrms->begin() + ns;
  194.        nb < rl->nrms->end(); nb += 3) {
  195.     Pnt3 n (nb[0], nb[1], nb[2]);
  196.     sxf (n);
  197.     nb[0] = n[0]; nb[1] = n[1]; nb[2] = n[2];
  198.   }
  199. }
  200.       }
  201.     }
  202.   }
  203.   return reglevels[iRes];
  204. }
  205. static Random rnd;
  206. void 
  207. CyberScan::subsample_points(float rate, vector<Pnt3> &p,
  208.     vector<Pnt3> &n)
  209.   regLevelData* level = getCurrentRegLevel();
  210.   int end = level->pnts->size();
  211.   p.clear(); p.reserve(end * rate * 1.1);
  212.   n.clear(); n.reserve(end * rate * 1.1);
  213.   for (int i = 0; i < end; i++) {
  214.     if (rnd() <= rate) {
  215.       p.push_back (level->pnts->operator[](i));    // save point
  216.       pushNormalAsPnt3 (n, level->nrms->begin(), i);
  217.     }
  218.   }
  219. }
  220. RigidScan* 
  221. CyberScan::filtered_copy (const VertexFilter &filter)
  222. {
  223.   BailDetector bail;
  224.   CyberScan *newScan = new CyberScan;
  225.   newScan->bDirty = true;
  226.   cout << "Clip " << sweeps.size() << " sweeps: " << flush;
  227.   for (int i = 0; i < sweeps.size(); i++) {
  228.     RigidScan* newSweep = sweeps[i]->filtered_copy(filter);
  229.     if (newSweep) {
  230.       CyberSweep *cs = dynamic_cast<CyberSweep*> (newSweep);
  231.       assert(cs);
  232.       newScan->sweeps.push_back(cs);
  233.     }
  234.     cout << "." << flush;
  235.     if (bail()) {
  236.       cerr << "Warning: clip interrupted; results are partial" << endl;
  237.       break;
  238.     }
  239.   }
  240.   cout << " " << newScan->sweeps.size() << " made it." << endl;
  241.   if (newScan->sweeps.size()) {
  242.     newScan->read_postprocess(get_name().c_str());
  243.     newScan->setXform (getXform());
  244.   }
  245.   return newScan;
  246. }
  247. RigidScan* 
  248. CyberScan::get_piece (int sweepNumber, int frameStart, int frameFinish)
  249. {
  250.   if (sweepNumber >= sweeps.size()) {
  251.     return NULL;
  252.   }
  253.   RigidScan* newSweep = 
  254.     sweeps[sweepNumber]->get_piece(frameStart, frameFinish);
  255.   if (newSweep == NULL)
  256.     return NULL;
  257.   CyberSweep *cs = dynamic_cast<CyberSweep*> (newSweep);
  258.   assert(cs);
  259.   CyberScan *newScan = new CyberScan;
  260.   newScan->sweeps.push_back(cs);
  261.   newScan->read_postprocess(get_name().c_str());
  262.   newScan->setXform (getXform());
  263.   return newScan;
  264. }
  265. bool 
  266. CyberScan::filter_inplace (const VertexFilter &filter)
  267. {
  268.   return false;
  269. }
  270. bool 
  271. CyberScan::filter_vertices (const VertexFilter &filter, 
  272.     vector<Pnt3>& p)
  273. {
  274.   for (int i=0; i<sweeps.size(); i++) {
  275.     CyberSweep *cs = sweeps[i];
  276.     int level = cs->current_resolution_index();
  277.     vector<Pnt3> &pnts = cs->levels[level]->pnts;
  278.     vector<Pnt3>::const_iterator it;
  279.     for (it = pnts.begin(); it != pnts.end(); it++) {
  280.       if (filter.accept(*it)) p.push_back(*it);
  281.     }
  282.   }
  283.   return true;
  284. }
  285. bool
  286. CyberScan::closest_point(const Pnt3 &p, const Pnt3 &n, 
  287.  Pnt3 &cp, Pnt3 &cn,
  288.  float thr, bool bdry_ok)
  289. {
  290.   KDindtree* tree = get_current_kdtree();
  291.   if (!tree) return false;
  292.   int ind, ans;
  293.   regLevelData* level = getCurrentRegLevel();
  294.   ans = tree->search(level->pnts->begin(), level->nrms->begin(), 
  295.      p, n, ind, thr);
  296.   if (ans) {
  297.     if (bdry_ok == 0) {
  298.       // disallow closest points that are on the mesh boundary
  299.       if (level->bdry->operator[](ind)) return 0;
  300.     }
  301.     cp = level->pnts->operator[](ind);
  302.     ind *= 3;
  303.     cn.set(level->nrms->operator[](ind  )/32767.0, 
  304.    level->nrms->operator[](ind+1)/32767.0, 
  305.    level->nrms->operator[](ind+2)/32767.0);
  306.   }
  307.   return ans;
  308. }
  309. void
  310. CyberScan::computeBBox ()
  311. {
  312.   bbox.clear();
  313.   for (int i = 0; i < sweeps.size(); i++) {
  314.     sweeps[i]->computeBBox();
  315.     if (sweeps[i]->bbox.valid())
  316.       bbox.add (sweeps[i]->bbox.worldBox (sweeps[i]->getXform()));
  317.   }
  318.   if (bbox.valid()) {
  319.     rot_ctr = bbox.center();
  320.   } else {
  321.     rot_ctr = Pnt3();
  322.   }
  323. }
  324. void
  325. CyberSweep::computeBBox ()
  326. {
  327.   bbox.clear();
  328.   // find highest built resolution
  329.   levelData* level = NULL;
  330.   for (int i = 0; i < levels.size(); i++) {
  331.     if (levels[i] != NULL && levels[i]->pnts.size() > 0) {
  332.       level = levels[i];
  333.       break;
  334.     }
  335.   }
  336.   // and add its points to bbox
  337.   if (level != NULL) {
  338.     for (Pnt3* p = level->pnts.begin(); p < level->pnts.end(); p++) {
  339.       bbox.add(*p);
  340.     }
  341.   }
  342. }
  343. void
  344. CyberScan::flipNormals (void)
  345. {
  346.   for (int i = 0; i < sweeps.size(); i++)
  347.     sweeps[i]->flipNormals();
  348. }
  349. void
  350. CyberSweep::flipNormals (void)
  351. {
  352.   for (int i = 0; i < levels.size(); i++) {
  353.     if (!resolutions[i].in_memory)
  354.       continue;
  355.     for (int j = 0; j < levels[i]->nrms.size(); j++) 
  356.       levels[i]->nrms[j] = -levels[i]->nrms[j];
  357.     flip_tris(levels[i]->tstrips, true);
  358.   }
  359. }
  360. bool 
  361. CyberScan::read(const crope &fname)
  362. {
  363.   cout << "cs::read()" << endl;
  364.   set_name (fname);
  365.   const char* filename = fname.c_str();
  366.   assert(has_ending(".sd") || has_ending(".sd.gz"));
  367.   // is filename a directory containing lots of little .sd files?
  368.   bool bReadDir = false;
  369.   SHOW(filename);
  370.   DirEntries de(filename, ".sd");
  371.   if (de.isdir)  {    // If it's a directory
  372.     bReadDir = true;
  373.     {
  374.       Progress progress (de.size(), "Read CyberSweeps");
  375.       for (; !de.done(); de.next()) {
  376.         CyberSweep *ct = new CyberSweep;
  377.         if (ct->read(de.path().c_str()))
  378.        sweeps.push_back(ct);
  379.         else
  380.   delete ct;
  381.         progress.updateInc();
  382.       }
  383.     }
  384.     DirEntries gzde(filename, ".sd.gz");
  385.     {
  386.       Progress progress (gzde.size(), "Read CyberSweeps");
  387.       for (; !gzde.done(); gzde.next()) {
  388.         CyberSweep *ct = new CyberSweep;
  389.         if (ct->read(gzde.path().c_str()))
  390.        sweeps.push_back(ct);
  391.         else
  392.   delete ct;
  393.         progress.updateInc();
  394.       }
  395.     }
  396.   } else {                           // If it's a single file
  397.     CyberSweep *ct = new CyberSweep;
  398.     if (ct->read(filename))
  399.       sweeps.push_back(ct);
  400.     else
  401.       delete ct;
  402.   }
  403.   // If we didn't successfully read any .sd files, return error
  404.   
  405.   if (sweeps.size() == 0)
  406.     return false;
  407.   set_name(fname);
  408.   // read registration xform?
  409.   if (TbObj::readXform (get_basename())) {
  410.     // if we read a single file instead of a directory,
  411.     // sweep will have read the same .xf as we do; 
  412.     // don't want it doubly applied so nuke it from sweep.
  413.     if (!bReadDir) {
  414.       assert (sweeps.size() == 1);
  415.       sweeps[0]->setXform (Xform<float>());
  416.       clear_undo (sweeps[0]);
  417.     }
  418.   }
  419.   clear_undo (this);
  420.   read_postprocess(filename);
  421.   return true;
  422. }
  423. bool
  424. CyberScan::is_modified (void)
  425. {
  426.   return bDirty;
  427. }
  428. bool 
  429. CyberScan::write(const crope &fname)
  430. {
  431.    char sweepfn[PATH_MAX];
  432.    if (fname.empty()) {
  433.       // try to save to default name; quit if there isn't one
  434.       if (name.empty()) return false;
  435.    }
  436.    else {
  437.       if (name != fname)  {
  438.          cout << "Saving to filename " << fname << endl;
  439.          set_name(fname);
  440.       }
  441.    }
  442.    
  443.    if (portable_mkdir(name.c_str(), 0775) == 0)  {
  444.       Progress progress (sweeps.size(), "Writing CyberScan");
  445.       for (int i=0; i<sweeps.size(); i++)  {
  446.          sprintf(sweepfn, "%s/%d.sd", name.c_str(), i);
  447.  if (!sweeps[i]->write(sweepfn))
  448.              return false;
  449.          progress.updateInc();
  450.       }
  451.    }
  452.    else
  453.       return false;
  454.   
  455.    bDirty = false;
  456.    return true;
  457. }
  458. bool
  459. CyberScan::load_resolution (int iRes)
  460. {
  461.   if (resolutions[iRes].in_memory)
  462.     return true;
  463.   int nSweeps = sweeps.size();
  464.   if (g_verbose) cout << name << ": create mesh (~" 
  465.        << resolutions[iRes].abs_resolution << ") from "
  466.        << nSweeps << " sweeps: " << flush;
  467.   int newres = 0;
  468.   BailDetector bail;
  469.   for (int i = 0; i < nSweeps; i++) {
  470.     //cout << (nSweeps - i) << " left: " << flush;
  471.     sweeps[i]->load_resolution (iRes);
  472.     newres += sweeps[i]->resolutions[iRes].abs_resolution;
  473.     if (g_verbose) cout << "." << flush;
  474.     if (bail()) {
  475.       return false;
  476.     }
  477.   }
  478.   if(g_verbose)  cout << " done." << endl;
  479.   resolutions[iRes].abs_resolution = newres;
  480.   resolutions[iRes].in_memory = true;
  481.   computeBBox();
  482.   return true;
  483. }
  484. int
  485. CyberScan::create_resolution_absolute(int budget, Decimator dec)
  486. {
  487.   cerr << "Can't decimate CyberScan meshes for now" << endl;
  488.   return 0;
  489. }
  490. bool
  491. CyberScan::release_resolution(int nPolys)
  492. {
  493.   int iRes = findLevelForRes (nPolys);
  494.   if (iRes == -1) {
  495.     cerr << "Cyber scan resolution doesn't exist!" << endl;
  496.     return false;
  497.   }
  498.   for (int i = 0; i < sweeps.size(); i++) {
  499.     delete sweeps[i]->levels[iRes];
  500.     sweeps[i]->levels[iRes] = new levelData;
  501.     sweeps[i]->resolutions[iRes].in_memory = false;
  502.   }
  503.   resolutions[iRes].in_memory = false;
  504.   return true;
  505. }
  506. /*
  507. void
  508. check(vector<int> &tstrips, int n) 
  509. {
  510.   int ns = tstrips.size();
  511.   for (int i=0; i<ns; i++) {
  512.     assert(tstrips[i] >=-1);
  513.     assert(tstrips[i] < n);
  514.   }
  515. }
  516. */
  517. extern DrawObjects draw_other_things;
  518. CyberSweep::CyberSweep(void)
  519. {
  520.   _cset.chooseNewColor(falseColor);
  521.   DrawObj::disable();
  522.   draw_other_things.add(this);
  523. }
  524. CyberSweep::~CyberSweep(void)
  525. {
  526.   while (kdtree.size()) {
  527.     delete (kdtree.back());
  528.     kdtree.pop_back();
  529.   }
  530.   while (levels.size()) {
  531.     delete (levels.back());
  532.     levels.pop_back();
  533.   }
  534.   draw_other_things.remove(this);
  535. }
  536. void
  537. CyberSweep::init_leveldata(void)
  538. {
  539.   levels.clear(); levels.reserve(SUBSAMPS);
  540.   kdtree.clear(); kdtree.reserve(SUBSAMPS);
  541.   for (int i = 0; i < SUBSAMPS; i++) {
  542.     levels.push_back (new levelData);
  543.     kdtree.push_back (NULL);
  544.   }
  545. }
  546. void
  547. CyberSweep::insert_possible_resolutions(void)
  548. {
  549.   for (int i = 0; i < SUBSAMPS; i++) {
  550.     int nFacesEstimated = 4 * sd.count_valid_pnts() / (1<<(2*i));
  551.     if (i > 0) {
  552.       insert_resolution(nFacesEstimated, "", false, false);
  553.       int iPos = findLevelForRes(nFacesEstimated);
  554.     } else {
  555.       insert_resolution(nFacesEstimated / 2, "", false, false);
  556.     }
  557.   }
  558. }
  559. bool
  560. CyberSweep::read(const crope &fname)
  561. {
  562.   if (!sd.read(fname))
  563.     return false;
  564.   set_name(fname);
  565.   init_leveldata();
  566.   insert_possible_resolutions();
  567.   if (g_verbose) cout << "done." << endl;
  568.   /*
  569.   Bbox bb = sd.get_bbox();
  570.   SHOW(bb);
  571. #if 1
  572.   int n = 8;
  573.   Pnt3 diff = bb.max() - bb.min(), p, bp;
  574.   for (int i=0; i<n; i++) {
  575.     for (int j=0; j<n; j++) {
  576.       for (int k=0; k<n; k++) {
  577. p = bb.min() + Pnt3(diff[0]*i, diff[1]*j, diff[2]*k)/n;
  578. if (sd.xf.back_project(p, bp)) {
  579.   // now go back to the data, find the closest
  580.   // data point
  581.   int row;
  582.   unsigned short y,z;
  583.   if (sd.find_data(bp[0], bp[1], row, y, z)) {
  584.     //SHOW(bp[1]);
  585.     //SHOW (y);
  586.     sd.set_xf(row);
  587.     //xf.set_screw(bp[0],bp[0]);
  588.     start.push_back(p);
  589.     end.push_back(sd.xf.apply_xform(y,z));
  590.     start.push_back(p);
  591.     //end.push_back(pa);
  592.     end.push_back(sd.xf.laser_ctr);
  593.     //start.push_back(.9*end.back()+.1*p);
  594.     //SHOW(start.back());
  595.     //SHOW(end.back());
  596.   } else {
  597.     cout << "find_data returns false" << endl;
  598.     //SHOW(bp);
  599.     //cout << row << " " << y << " " << z << endl;
  600.   }
  601. } else {
  602.   cout << "back_project returns false" << endl;
  603. }
  604.       }
  605.     }
  606.   }
  607. #else
  608.   Pnt3 p;
  609.   for (int i=0; i<sd.num_frames(); i+=40) {
  610.     for (int j=40; j<480; j+=40) {
  611.       sd.set_xf(i);
  612.       if (sd.get_point(i,j,p)) {
  613. start.push_back(p);
  614. end.push_back(sd.xf.laser_ctr);
  615.       }
  616.     }
  617.   }
  618. #endif
  619.   DrawObj::enable();
  620.   */
  621.   if (TbObj::readXform (get_basename()))
  622.     cout << "Found .xf for sweep " << fname << endl;
  623.   //else
  624.   //cout << "No .xf for sweep " << fname << endl;
  625.   return true;
  626. }
  627. bool
  628. CyberSweep::write(const crope &fname)
  629. {
  630.   return sd.write(fname);
  631. }
  632. // called by CyberScan::load_resolution(),
  633. // which again is inherited from ResolutionCtrl
  634. bool
  635. CyberSweep::load_resolution (int iRes)
  636. {
  637.   if (resolutions[iRes].in_memory)
  638.     return true;
  639.   //cout << "tstrip... " << flush;
  640.   if (iRes == 0) {
  641.     sd.get_pnts_and_intensities(levels[0]->pnts,
  642. levels[0]->intensity);
  643.     // Changed the following line into a two step process, to avoid
  644.     // Compiler complaint. -jed
  645.     //levels[0]->bdry.assign (levels[0]->pnts.size(), 0);
  646.     vector<char> tmp(levels[0]->pnts.size(), 0);
  647.     levels[0]->bdry = tmp;
  648.     
  649.     sd.make_tstrip(levels[0]->tstrips, levels[0]->bdry);
  650.   } else {
  651.     levelData* level = levels[iRes];
  652.     int step = 1 << iRes;
  653.     sd.subsampled_tstrip(step, 
  654.  Tcl_GetVar (g_tclInterp,
  655.      "subsamplePreserveHoles",
  656.      TCL_GLOBAL_ONLY),
  657.  level->tstrips,
  658.  level->bdry,
  659.  level->pnts,
  660.  level->intensity,
  661.  level->confidence,
  662.  level->map_sampled_to_unsampled);
  663.   }
  664.   // now fix step edges, normals
  665.   levelData* level = levels[iRes];
  666.   if (level->pnts.size()) {
  667.     if (strcmp (Tcl_GetVar (g_tclInterp, "removeStepedges",
  668.     TCL_GLOBAL_ONLY), "0") != 0) {
  669.       //cout << "stepedges... " << flush;
  670.       remove_stepedges(level->pnts, level->tstrips, 4, 50, true);
  671.     }
  672.     //cout << "normals... " << flush;
  673.     getVertexNormals(level->pnts, level->tstrips,
  674.      true, level->nrms, false);
  675.     
  676.     resolutions[iRes].abs_resolution = 
  677.       count_tris (levels[iRes]->tstrips);
  678.   } else {
  679.     resolutions[iRes].abs_resolution = 0;
  680.   }
  681.   resolutions[iRes].in_memory = true;
  682.   return true;
  683. }
  684. void 
  685. CyberSweep::drawthis(void)
  686. {
  687.   glDisable(GL_LIGHTING);
  688.   glBegin(GL_LINES);
  689.   for (int i=0; i<start.size(); i++) {
  690.     glColor3f(1,0,0); 
  691.     glVertex3fv(&start[i][0]);
  692.     glColor3f(0,1,0);
  693.     glVertex3fv(&end[i][0]);
  694.   }
  695.   glEnd();
  696. }
  697. /* kberg - 10 July 2001
  698.  * adding per face normals - modeled partly after strips_to_tris
  699.  * in TriMeshUtils.cc, except rather than storing the vertices, it 
  700.  * calculates a normal based upon those 3 vertices then adds it to
  701.  * the faceNormals vector.
  702.  */
  703. void CyberSweep::simulateFaceNormals(vector<short> &faceNormals, int currentRes)
  704. {
  705.   if (!levels[currentRes]->tstrips.size())
  706.     return;
  707.   
  708.   assert(levels[currentRes]->tstrips.back() == -1);
  709.   
  710.   faceNormals.clear();
  711.   faceNormals.reserve(levels[currentRes]->tstrips.size() * 3); // estimate
  712.   
  713.   vector<int>::const_iterator vert;
  714.   for (vert = levels[currentRes]->tstrips.begin(); vert != levels[currentRes]->tstrips.end(); vert++) {
  715.     while (*vert == -1) { // handle 0-length strips
  716.       ++vert;
  717.       if (vert == levels[currentRes]->tstrips.end()) break;
  718.     }
  719.     if (vert == levels[currentRes]->tstrips.end()) break;
  720.     
  721.     vert += 2; // looking backwards at the triangles
  722.     
  723.     int dir = 0;
  724.     while (*vert != -1) {
  725.       Pnt3 &v0 = levels[currentRes]->pnts[vert[-2 + dir]];
  726.       Pnt3 &v1 = levels[currentRes]->pnts[vert[-1 - dir]];
  727.       Pnt3 &v2 = levels[currentRes]->pnts[vert[0]];
  728.       
  729.       //now calculate the normal based on these 3 points
  730.       Pnt3 norm = normal(v0, v1, v2);
  731.       pushNormalAsShorts(faceNormals, norm);
  732.       vert++;
  733.       dir ^= 1;
  734.     }
  735.   }
  736. }
  737. MeshTransport*
  738. CyberSweep::mesh (bool perVertex, bool stripped,
  739.   ColorSource color, int colorSize)
  740. {
  741.   int i = current_resolution_index();
  742.   assert (resolutions[i].in_memory);
  743.   if (!levels[i]->pnts.size())
  744.     return NULL;
  745.   MeshTransport* mt = new MeshTransport;
  746.   mt->setVtx(&levels[i]->pnts, MeshTransport::share);
  747.   mt->setBbox(localBbox());
  748.   
  749.   /* kberg - 10 July 2001 - per face normals */
  750.   if (perVertex)
  751.     mt->setNrm(&levels[i]->nrms, MeshTransport::share);
  752.   else {
  753.     /* used GenericScan::mesh(...) as an example of how to simulate this. 
  754.        for some reason, by going into this mode, only part of a statue
  755.        is displayed when intensity is selected.  It should have something to do
  756.        with how DisplayMesh::renderMeshSingle(...) handles color.
  757.     */
  758.     vector<short> *faceNrm = new vector<short>;
  759.     simulateFaceNormals(*faceNrm, i);
  760.     mt->setNrm(faceNrm, MeshTransport::steal);
  761.   }
  762.   if (stripped) {
  763.     mt->setTris(&levels[i]->tstrips, MeshTransport::share);
  764.   } else {
  765.     vector<int>* tris = new vector<int>;
  766.     strips_to_tris (levels[i]->tstrips, *tris,
  767.     resolutions[i].abs_resolution);
  768.     mt->setTris(tris, MeshTransport::steal);
  769.   }
  770.   
  771.   switch (color) {
  772.   case colorNone:
  773.     break;
  774.     
  775.   case colorTrue:
  776.     {
  777.       vector<uchar>* colors = new vector<uchar>;
  778.       pushColor (*colors, colorSize, falseColor);
  779.       mt->setColor (colors, MeshTransport::steal);
  780.     }
  781.     break;
  782.   case colorIntensity:
  783.     {
  784.       vector<uchar>* colors = new vector<uchar>;
  785.       if (g_bNoIntensity) {
  786. // BUGBUG: what to do here?
  787.       } else {
  788. uchar* end = levels[i]->intensity.end();
  789. for (uchar* c = levels[i]->intensity.begin(); c < end; c++)
  790.   pushColor (*colors, colorSize, *c);
  791.       }
  792.       mt->setColor (colors, MeshTransport::steal);
  793.     }
  794.     break;
  795.   case colorConf:
  796.     if (levels[i]->confidence.size())
  797.     {
  798.       vector<uchar>* colors = new vector<uchar>;
  799.       colors->reserve (colorSize * levels[i]->confidence.size());
  800.       uchar* end = levels[i]->confidence.end();
  801.       for (uchar* c = levels[i]->confidence.begin(); c < end; c++)
  802. pushConf (*colors, colorSize, *c);
  803.       mt->setColor (colors, MeshTransport::steal);
  804.     }
  805.     break;
  806.   case colorBoundary:
  807.     {
  808.       vector<uchar>* colors = new vector<uchar>;
  809.       colors->reserve (colorSize * levels[i]->bdry.size());
  810.       char* end = levels[i]->bdry.end();
  811.       for (char* c = levels[i]->bdry.begin(); c < end; c++)
  812. pushConf (*colors, colorSize, (uchar)(*c ? 0 : 255));
  813.       mt->setColor (colors, MeshTransport::steal);
  814.     }
  815.     break;
  816.     
  817.   default:
  818.     //cerr << "Color: TODO" << endl;
  819.     break;
  820.   }
  821.   return mt;
  822. }
  823. vector<CyberSweep*>
  824. CyberScan::get_sweep_list (void)
  825. {
  826.   return sweeps;
  827. }
  828. // double indexing: horizontal translation, turns
  829. vector< vector<CyberSweep*> >
  830. CyberScan::get_ordered_sweeps (void)
  831. {
  832.   vector< vector<CyberSweep*> > v;
  833.   // for each sweep
  834.   for (int i=0; i < sweeps.size(); i++) {
  835.     CyberSweep* sweep = sweeps[i];
  836.     // insert a vector in v based on translation
  837.     float t = sweep->sd.scanner_trans;
  838.     for (int iTrans = 0; iTrans < v.size(); iTrans++) {
  839.       float tc = v[iTrans][0]->sd.scanner_trans;
  840.       if (t <= tc) {
  841. if (t < tc) v.insert(&v[iTrans], vector<CyberSweep*>());
  842. break;
  843.       }
  844.     }
  845.     if (iTrans == v.size()) v.push_back( vector<CyberSweep*>() );
  846.     // get a reference to the shell
  847.     vector<CyberSweep*>& vShell = v[iTrans];
  848.     // find a place to insert sweep (within shell) 
  849.     // based on other screw
  850.     for (int iSweep = 0; iSweep < vShell.size(); iSweep++) {
  851.       if (sweep->sd.other_screw < vShell[iSweep]->sd.other_screw)
  852. break;
  853.     }
  854.     // insert into shell
  855.     vShell.insert (&vShell[iSweep], sweep);
  856.   }
  857.   return v;
  858. }
  859. // this command dumps into the file fname
  860. // nPnts uniformly subsampled from all the sweeps
  861. // such that there are nPnts output
  862. // for each point, there are 5 floats: y,z,scanscrew,otherscrew,xform
  863. // file is initialized with 1 for vertical scan, 0 for horizontal scan
  864. void
  865. CyberScan::dump_pts_laser_subsampled(std::string fname,
  866.      int nPnts)
  867. {
  868.   // open the fstream
  869.   ofstream out(fname.c_str());
  870.   assert(out);
  871.   // vertical scan?
  872.   int v = sweeps[0]->sd.xf.vertical_scan;
  873.   out.write((char*)&v, sizeof(int));
  874.   // for each sweep, calculate how many points it should
  875.   // store, have it store them
  876.   int n_valid_pts = 0;
  877.   // first, how many valid points are there?
  878.   for (int i=0; i < sweeps.size(); i++) {
  879.     n_valid_pts += sweeps[i]->sd.valid_pts();
  880.   }  
  881.   // now, iterate
  882.   SHOW(nPnts);
  883.   float fact = float(nPnts) / float(n_valid_pts);
  884.   for (i=0; i < sweeps.size(); i++) {
  885.     int n = sweeps[i]->sd.valid_pts();
  886.     n_valid_pts -= n;
  887.     if (i+1 == sweeps.size()) n = nPnts;
  888.     else                      n *= fact;
  889.     nPnts -= sweeps[i]->sd.dump_pts_laser_subsampled(out, n);
  890.     fact = float(nPnts) / float(n_valid_pts);
  891.   }  
  892.   SHOW(nPnts);
  893. }
  894. // this function is intended to be used for getting the raw values
  895. // for a given 3D point (given in local coordinates)
  896. // used in conjunction with autocalibration
  897. // assume the mesh has just been registered with ICP
  898. bool
  899. CyberScan::get_raw_data(const Pnt3 &p, sd_raw_pnt &data)
  900. {
  901.   // to simplify things, only works at finest resolution
  902.   //int lvl = 0;
  903.   int lvl = current_resolution_index();
  904.   //if (current_resolution_index() != lvl) return false;
  905.   // and the KDtree has to exist
  906.   if (kdtree[lvl] == NULL) return false;
  907.   // and the reglevelinfo
  908.   if (reglevels[lvl] == NULL) return false;
  909.   // ok. assume p is in the scan coordinates, by the way
  910.   
  911.   // find the index of the point closest to p in kdtree
  912.   int ind;
  913.   float thr = .1;
  914.   if (!kdtree[lvl]->search(reglevels[lvl]->pnts->begin(),
  915.    p, ind, thr)) {
  916.     cerr << "Couldn't find the point " << p << endl;
  917.     return false;
  918.   }
  919.   // ok, found the point index
  920.   // now, find which sweep it is and find the relative index there
  921.   for (int i=0; i<sweeps.size(); i++) {
  922.     int n = sweeps[i]->levels[lvl]->pnts.size();
  923.     if (ind >= n) ind -= n;
  924.     else          break;
  925.   }
  926.   if (i==sweeps.size()) {
  927.     cerr << "Problem in CyberScan::get_raw_data()" << endl;
  928.     return false;
  929.   }
  930.   // now we have the index to the sweep and an index to the
  931.   // point there
  932.   Pnt3  pp;
  933.   if (lvl) {
  934.     ind = sweeps[i]->levels[lvl]->map_sampled_to_unsampled[ind];
  935.     pp = sweeps[i]->sd.raw_for_ith(ind, data);
  936.   } else {
  937.     pp = sweeps[i]->sd.raw_for_ith_valid(ind, data);
  938.   }
  939.   
  940.   if (dist(pp,p) > .1) {
  941.     SHOW(p);
  942.     SHOW(pp);
  943.     SHOW(dist(p,pp));
  944.   }
  945.   
  946.   return true;
  947. }
  948. // returns confidence!
  949. float 
  950. CyberScan::closest_point_on_mesh(const Pnt3 &p, Pnt3 &cl_pnt, 
  951.  OccSt &status_p)
  952. {
  953.   // cheat...
  954.   return closest_along_line_of_sight(p, cl_pnt, status_p);
  955. }
  956.  
  957. // returns confidence!
  958. float 
  959. CyberScan::closest_along_line_of_sight(const Pnt3 &p, Pnt3 &cp, 
  960.        OccSt &status_p)
  961. {
  962.   // first need to move p into the local coordinates!!
  963.   Pnt3 pp = p;
  964.   xformInvPnt(pp);
  965.   // simplified assumptions... recheck later
  966.   // e.g., assume no per sweep xforms...
  967.   status_p = INDETERMINATE;
  968.   float mindist = 1e33;
  969.   OccSt tmp;
  970.   Pnt3  tmpcp;
  971.   for (int i=0; i<sweeps.size(); i++) {
  972.     sweeps[i]->closest_along_line_of_sight(pp,tmpcp,tmp);
  973.     if (status_p == INDETERMINATE && tmp == NOT_IN_FRUSTUM) {
  974.       status_p = tmp;
  975.       continue;
  976.     }
  977.     // should make a weighted sum of distances, see VolCarve.cc
  978.     float d = dist2(pp, tmpcp);
  979.     if (d < mindist) {
  980.       mindist  = d;
  981.       status_p = tmp;
  982.       cp       = tmpcp;
  983.     }
  984.   }
  985.   // move closest point back into world coordinates!
  986.   xformPnt(cp);
  987.   // return confidence
  988.   return (status_p == INSIDE || status_p == OUTSIDE ? 1.0 : 0.0);
  989. }
  990.  
  991. OccSt
  992. CyberScan::carve_cube  (const Pnt3 &ctr, float side)
  993. {
  994.   // first of all, we are going to carve a sphere s.t.
  995.   // the ctr is reexpressed in local coordinates
  996.   Pnt3 lctr(ctr);
  997.   xformInvPnt(lctr);
  998.   float r = 1.72 * .5 * side;
  999.   // find a parent from the carve stack for this sphere
  1000.   while (carveStack.size() &&
  1001.  !carveStack.back().can_be_child(ctr, side)) {
  1002.     carveStack.pop_back();
  1003.   }
  1004.   if (carveStack.size() == 0) {
  1005.     // initialize with all
  1006.     carveStack.push_back(carveStackEntry(lctr, r, sweeps));
  1007.   }
  1008.   
  1009.   // now the back() of the stack should have the sweeps that
  1010.   // we're interested in
  1011.   vector<CyberSweep*> &sw = carveStack.back().sweeps;
  1012.   
  1013.   // add a new entry for this cube
  1014.   carveStackEntry cse(lctr, r);
  1015.   // go through all the sweeps in the list
  1016.   OccSt res = INDETERMINATE;
  1017.   for (int i=0; i<sw.size(); i++) {
  1018.     OccSt tmp = sw[i]->carve_sphere(lctr, r);
  1019.     // add the current to the stack if needed
  1020.     if (tmp == BOUNDARY ||
  1021. tmp == SILHOUETTE ||
  1022. tmp == INDETERMINATE) {
  1023.       cse.sweeps.push_back(sw[i]);
  1024.     }
  1025.     if (int(tmp) < int(res)) res = tmp;
  1026.     if (res == OUTSIDE) return res;
  1027.   }
  1028.   carveStack.push_back(cse);
  1029.   return res;
  1030. }
  1031. bool
  1032. CyberScan::switchToResLevel (int iRes)
  1033. {
  1034.   if (!RigidScan::switchToResLevel (iRes))
  1035.     return false;
  1036.   // keep all sweeps synched to current res
  1037.   for (int i = 0; i < sweeps.size(); i++)
  1038.     sweeps[i]->switchToResLevel (iRes);
  1039.   return true;
  1040. }
  1041. crope
  1042. CyberSweep::get_description (void) const
  1043. {
  1044.   static char name[100];
  1045.   sprintf(name, "trans-%.2d-rot-%.2d",
  1046.   (int)sd.scanner_trans,
  1047.   (int)sd.other_screw);
  1048.   return crope (name);
  1049. }
  1050. KDindtree*
  1051. CyberSweep::get_current_kdtree()
  1052. {
  1053.   int iTree = current_resolution_index();
  1054.   assert (iTree < kdtree.size());
  1055.   if (kdtree[iTree] != NULL)
  1056.     return kdtree[iTree];
  1057.   levelData* level = levels[current_resolution_index()];
  1058.   kdtree[iTree] = CreateKDindtree(level->pnts.begin(), 
  1059.   level->nrms.begin(),
  1060.   level->pnts.size());
  1061.   return kdtree[iTree];
  1062. }
  1063. void 
  1064. CyberSweep::subsample_points(float rate, vector<Pnt3> &p,
  1065.      vector<Pnt3> &n)
  1066.   levelData* level = levels[current_resolution_index()];
  1067.   int end = level->pnts.size();
  1068.   p.clear(); p.reserve(end * rate * 1.1);
  1069.   n.clear(); n.reserve(end * rate * 1.1);
  1070.   for (int i = 0; i < end; i++) {
  1071.     if (rnd() <= rate) {
  1072.       p.push_back(level->pnts[i]);    // save point
  1073.       pushNormalAsPnt3(n, level->nrms.begin(), i);
  1074.     }
  1075.   }
  1076. }
  1077. RigidScan *
  1078. CyberSweep::filtered_copy(const VertexFilter &filter)
  1079. {
  1080.   CyberSweep* newSweep = NULL;
  1081.   // need to multiply filter by this sweep's xform
  1082.   VertexFilter* sweepFilter = filter.transformedClone ((float*)getXform());
  1083.   if (!sweepFilter) {
  1084.     cerr << "CyberScan cannot clip because VertexFilter::transformedClone"
  1085.  << " is not supported" << endl;
  1086.     return NULL;
  1087.   }
  1088.   if (sweepFilter->accept (bbox)) {
  1089.     newSweep = new CyberSweep;
  1090.     // copy the data, first shallow copy
  1091.     //*newSweep = *this;
  1092.     // except resolutions, which get rebuilt
  1093.     // newSweep->resolutions.clear();
  1094.     // then do a deeper, filtered copy
  1095.     newSweep->init_leveldata();
  1096.     sd.filtered_copy(*sweepFilter, newSweep->sd);
  1097.     if (sd.count_valid_pnts() == 0) {
  1098.       delete newSweep;
  1099.       newSweep = NULL;
  1100.     } else {
  1101.       newSweep->insert_possible_resolutions();
  1102.       newSweep->setXform (getXform());
  1103.     }
  1104.   }
  1105.   delete sweepFilter;
  1106.   return newSweep;
  1107. }
  1108. bool
  1109. CyberSweep::closest_point(const Pnt3 &p, const Pnt3 &n, 
  1110.   Pnt3 &cp, Pnt3 &cn,
  1111.   float thr, bool bdry_ok)
  1112. {
  1113.   KDindtree* tree = get_current_kdtree();
  1114.   if (!tree) return false;
  1115.   int ind, ans;
  1116.   levelData* level = levels[current_resolution_index()];
  1117.   ans = tree->search(&level->pnts[0], &level->nrms[0], 
  1118.      p, n, ind, thr);
  1119.   if (ans) {
  1120.     if (bdry_ok == 0) {
  1121.       // disallow closest points that are on the mesh boundary
  1122.       if (level->bdry[ind]) return 0;
  1123.     }
  1124.     cp = level->pnts[ind];
  1125.     ind *= 3;
  1126.     cn.set(level->nrms[ind  ]/32767.0, 
  1127.    level->nrms[ind+1]/32767.0, 
  1128.    level->nrms[ind+2]/32767.0);
  1129.   }
  1130.   return ans;
  1131. }
  1132. crope
  1133. CyberScan::getInfo (void)
  1134. {
  1135.   long verts = 0;
  1136.   long tris = 0;
  1137.   for (int i = 0; i < sweeps.size(); i++) {
  1138.     verts += sweeps[i]->sd.count_valid_pnts();
  1139.     tris =+ sweeps[i]->resolutions[0].abs_resolution;
  1140.   }
  1141.   char infos[512];
  1142.   sprintf(infos, "CyberScan: verts %ld stripped tris %ldnn",
  1143.   verts, tris);
  1144.   crope info (infos);
  1145.   if (sweeps.size() == 1) {
  1146.     info += crope ("Single sweep at ") + sweeps[0]->get_description();
  1147.     info += crope ("nFrom file: ") + sweeps[0]->get_name();
  1148.   } else {
  1149.     float turnMin = FLT_MAX; float transMin = FLT_MAX;
  1150.     float turnMax = -FLT_MAX; float transMax = -FLT_MAX;
  1151.     int lastShell = -1000;
  1152.     int nShells = 0;
  1153.     
  1154.     for (int i = 0; i < sweeps.size(); i++) {
  1155.       turnMin = MIN (turnMin, sweeps[i]->sd.other_screw);
  1156.       turnMax = MAX (turnMin, sweeps[i]->sd.other_screw);
  1157.       transMin = MIN (transMin, sweeps[i]->sd.scanner_trans);
  1158.       transMax = MAX (transMin, sweeps[i]->sd.scanner_trans);
  1159.       
  1160.       if ((int)sweeps[i]->sd.scanner_trans != lastShell) {
  1161. lastShell = sweeps[i]->sd.scanner_trans;
  1162. ++nShells;
  1163.       }
  1164.     }
  1165.       
  1166.     sprintf (infos, "%ld sweeps ranging:n"
  1167.      "Other-screw (nod/turn): %.2f to %.2fn"
  1168.      "Translation: %.2f to %.2f in %d shells",
  1169.      sweeps.size(), turnMin, turnMax, transMin, transMax, nShells);
  1170.     info += crope (infos);
  1171.   }
  1172.   info += crope ("nn") + RigidScan::getInfo();
  1173.   return info;
  1174. }
  1175. unsigned int
  1176. CyberScan::get_scanner_config(void)
  1177. {
  1178.    return sweeps[0]->sd.scanner_config;
  1179. }
  1180. float
  1181. CyberScan::get_scanner_vertical(void)
  1182. {
  1183.    return sweeps[0]->sd.scanner_vert;
  1184. }
  1185. //
  1186. // This function converts a point from world coordinates (X,Y,Z) to
  1187. // sweep coordinates (screw length, y, and z for a specific sweep).
  1188. //
  1189. bool
  1190. CyberScan::worldCoordToSweepCoord(const Pnt3 &wc, int *sweepIndex, Pnt3 &sc)
  1191. {
  1192.    Pnt3 csc, swc, bpp, fpp;
  1193.    bool gotOneFlag = false;
  1194.    float theDist, minDist = MAXFLOAT;
  1195.    CyberXform cxf;
  1196.    // First transform the world coord to the CyberScan coordinate
  1197.    // system by multiplying by the inverse of the CyberScan's Xform.
  1198.    getXform().apply_inv(wc, csc);
  1199.    
  1200.    // Next, iterate over all the sweeps, backprojecting the
  1201.    // transformed world coordinate to the sweep's coordinates.
  1202.    // If there are any valid backprojected points, we will return
  1203.    // the one with the minimum distance from the original point.
  1204.    for (int j=0; j<sweeps.size(); ++j)
  1205.    {
  1206.       // Apply the inverse of the individual sweep xform
  1207.       (sweeps[j]->getXform()).apply_inv(csc, swc);
  1208.       cxf.setup(sweeps[j]->sd.scanner_config,  // Need to add vertical screw
  1209. sweeps[j]->sd.scanner_trans,   // value to "setup" call when
  1210. sweeps[j]->sd.other_screw);    // we start using it in SDfile.
  1211.       //puts ("checking sweep");
  1212.  
  1213.       if (cxf.back_project(swc, bpp, true)) {
  1214. cout <<"back project success" << j << "  " << bpp << "n" << flush;
  1215.  sweepCoordToWorldCoord(j, bpp, fpp);
  1216.  theDist = dist2(wc, fpp);
  1217.  if (theDist < minDist) {
  1218.     sc = bpp;
  1219.     *sweepIndex = j;
  1220.     minDist = theDist;
  1221.     gotOneFlag = true;
  1222.          }
  1223.       }
  1224.    }
  1225.    return gotOneFlag;
  1226. }
  1227. //
  1228. // This function converts to world coordinates (X,Y,Z) from
  1229. // sweep coordinates (screw length, y, and z for a specific sweep).
  1230. //
  1231. void
  1232. CyberScan::sweepCoordToWorldCoord(int sweepIndex, const Pnt3 &sc, Pnt3 &wc)
  1233. {
  1234.    CyberXform cxf;
  1235.    //out << "In s2s"  << flush;
  1236.    // First, use the sweep configuration information and convert
  1237.    // to the sweep coordinate system.
  1238.    cxf.setup(sweeps[sweepIndex]->sd.scanner_config,  // Need to add vertical
  1239.              sweeps[sweepIndex]->sd.scanner_trans,   // screw value to "setup"
  1240.              sweeps[sweepIndex]->sd.other_screw);    // call at some point!!!
  1241.    cxf.set_screw(sc[0]);
  1242.    cxf.apply_xform((short) sc[1], (short) sc[2], wc);
  1243.    // Next, apply the transformation for the individual sweep.
  1244.    (sweeps[sweepIndex]->getXform())(wc);
  1245.    // Finally, apply the CyberScan's transformation.
  1246.    getXform()(wc);
  1247.    //out << "Out 2s"  << flush;
  1248. }
  1249. RigidScan *
  1250. CyberSweep::get_piece(int firstFrame, int lastFrame)
  1251. {
  1252.   // Does firstFrame have to be even???
  1253.   if (IS_ODD(firstFrame)) {
  1254.     cout << "CyberSweep::get_piece() Not tested with odd start frames!!" << endl;
  1255.   }
  1256.   if (firstFrame <  0 ||
  1257.       lastFrame  >= sd.num_frames() ||
  1258.       lastFrame  <  firstFrame) {
  1259.     return NULL;
  1260.   }
  1261.   CyberSweep *newSweep = new CyberSweep;
  1262.   newSweep->init_leveldata();
  1263.   sd.get_piece(firstFrame, lastFrame, newSweep->sd);
  1264.   if (newSweep->sd.count_valid_pnts() == 0) {
  1265.     delete newSweep;
  1266.     return NULL;
  1267.   }
  1268.   newSweep->insert_possible_resolutions();
  1269.   return newSweep;
  1270. }
  1271. // return confidence!
  1272. float 
  1273. CyberSweep::closest_along_line_of_sight(const Pnt3 &p, Pnt3 &cp, 
  1274. OccSt &status_p)
  1275. {
  1276.   Pnt3 bp;
  1277.   if (!sd.xf.back_project(p, bp)) {
  1278.     status_p = NOT_IN_FRUSTUM; 
  1279.     return 0.0;
  1280.   } 
  1281.   int row;
  1282.   unsigned short y,z; 
  1283.   if (!sd.find_data(bp[0], bp[1], row, y, z)) {
  1284.     status_p = NOT_IN_FRUSTUM;
  1285.     return 0.0;
  1286.   }
  1287.   sd.set_xf(row, false); 
  1288.   sd.xf.apply_xform(y,z,cp);
  1289.   status_p = (z > bp[2]) ? INSIDE : OUTSIDE;
  1290.   return 1.0;
  1291. }
  1292.  
  1293. OccSt
  1294. CyberSweep::carve_sphere(const Pnt3 &ctr, float r)
  1295. {
  1296.   return OccSt(sd.sphere_status(ctr, r));
  1297. }