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

3D图形编程

开发平台:

Visual C++

  1. #include <stdio.h>
  2. #include "ply++.h"
  3. #include <stdlib.h>
  4. #include "strings.h"
  5. #include "plvGlobals.h"
  6. #include "RangeGrid.h"
  7. #include "Mesh.h"
  8. #include <iostream.h>
  9. #ifdef WIN32
  10. #include <io.h>
  11. #endif
  12. #include <malloc.h>
  13. #include <math.h>
  14. #include <fcntl.h>
  15. #ifndef linux
  16. #    include <stdexcept.h>
  17. #endif
  18. #include "cyfile.h"
  19. #include "defines.h"
  20. #include "Xform.h"
  21. #include "Pnt3.h"
  22. struct PlyVertex {
  23.   float x,y,z;
  24.   float confidence;
  25.   float intensity;
  26.   unsigned char red,grn,blu;
  27. };
  28. PlyProperty vert_std_props[] = {
  29.   {"x", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,x), 0, 0, 0, 0},
  30.   {"y", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,y), 0, 0, 0, 0},
  31.   {"z", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,z), 0, 0, 0, 0},
  32.   {"confidence", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,confidence), 0, 0, 0,0},
  33.   {"intensity", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,intensity), 0, 0, 0,0},
  34.   {"diffuse_red", PLY_UCHAR, PLY_UCHAR, offsetof(PlyVertex,red), 0, 0, 0, 0},
  35.   {"diffuse_green", PLY_UCHAR, PLY_UCHAR, offsetof(PlyVertex,grn), 0, 0, 0, 0},
  36.   {"diffuse_blue", PLY_UCHAR, PLY_UCHAR, offsetof(PlyVertex,blu), 0, 0, 0, 0},
  37.   {"std_dev", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,confidence), 0, 0, 0,0},
  38. };
  39. struct RangePnt {
  40.   unsigned char num_pts;
  41.   int *pts;
  42. };
  43. // list of property information for a range data point
  44. PlyProperty range_props[] = {
  45.   {"vertex_indices", PLY_INT, PLY_INT, offsetof(RangePnt,pts),
  46.    1, PLY_UCHAR, PLY_UCHAR, offsetof(RangePnt,num_pts)},
  47. };
  48. static float RANGE_DATA_SIGMA_FACTOR = 4;
  49. static float RANGE_DATA_MIN_INTENSITY = 0.05;
  50. RangeGrid::RangeGrid()
  51. {
  52.   coords = NULL;
  53.   confidence = NULL;
  54.   intensity = NULL;
  55.   matDiff = NULL;
  56.   indices = NULL;
  57.   
  58.   hasColor = FALSE;
  59.   hasConfidence = FALSE;
  60.   hasIntensity = FALSE;
  61.   hasTexture = FALSE;
  62.   
  63.   obj_info = NULL;
  64.   num_obj_info = 0;
  65.   isModelMakerScan = FALSE;
  66. }
  67. RangeGrid::~RangeGrid()
  68. {
  69.   delete [] coords;
  70.   
  71.   delete [] indices;
  72.   
  73.   if (num_obj_info > 0) {
  74.     for (int i = 0; i < num_obj_info; i++)
  75.       delete [] obj_info[i];
  76.     delete [] obj_info;
  77.   }
  78.   
  79.   if (hasConfidence)
  80.     delete [] confidence;
  81.   
  82.   if (hasColor)
  83.     delete [] matDiff;
  84.   
  85.   if (hasIntensity)
  86.     delete [] intensity;
  87. }
  88. int 
  89. is_range_grid_file(const char *filename)
  90. {
  91.   int nelems;
  92.   char **elist;
  93.   PlyFile ply;
  94.   if (ply.open_for_reading(filename, &nelems, &elist) == 0)
  95.     return 0;
  96.   
  97.   for (int i = 0; i < nelems; i++) {
  98.     if (!strcmp(elist[i], "range_grid"))
  99.       return 1;
  100.   }
  101.   return 0;
  102. }
  103. /*****************************************************************
  104. Read range data from a PLY file.
  105. Entry:
  106.   name - name of PLY file to read from
  107. Exit:
  108.   returns pointer to data, or NULL if it couldn't read from file
  109. ******************************************************************/
  110. int
  111. RangeGrid::readRangeGrid(const char *name)
  112. {
  113.   int i,j,k,index, best_index;
  114.   PlyFile ply;
  115.   int num_elems;
  116.   int nprops;
  117.   int nelems;
  118.   char **elist;
  119.   PlyProperty **plist;
  120.   int num_rows,num_cols;
  121.   RangePnt range_pnt;
  122.   PlyVertex vert;
  123.   char *elem_name;
  124.   int get_std_dev = 0;
  125.   int get_confidence = 0;
  126.   int get_intensity = 0;
  127.   int get_color = 0;
  128.   int has_red = 0;
  129.   int has_green = 0;
  130.   int has_blue = 0;
  131.   int is_warped = 0;
  132.   char temp[PATH_MAX];
  133.   int isRightMirrorOpen = 1;
  134.   //int found_mirror = 0;  //unused?
  135.   int foundScanType = FALSE;
  136.   float conf,std;
  137.   float min_std,max_std,max;
  138.   float avg_std = 0;
  139.   if (ply.open_for_reading(name, &nelems, &elist) == 0)
  140.     return 0;
  141.   // parse the obj_info
  142.   char **ply_obj_info;
  143.   int ply_num_obj_info;
  144.   ply_obj_info = ply.get_obj_info (&ply_num_obj_info);
  145.   for (i = 0; i < ply_num_obj_info; i++) {
  146.     if (strstr(ply_obj_info[i], "num_cols"))
  147.       sscanf(ply_obj_info[i], "%s%d", temp, &num_cols);
  148.     if (strstr(ply_obj_info[i], "num_rows"))
  149.       sscanf(ply_obj_info[i], "%s%d", temp, &num_rows);
  150.     if (strstr(ply_obj_info[i], "is_warped"))
  151.       sscanf(ply_obj_info[i], "%s%d", temp, &is_warped);
  152.     if (strstr(ply_obj_info[i], "optimum_std_dev"))
  153.       sscanf(ply_obj_info[i], "%s%f", temp, &avg_std);
  154.     if (strstr(ply_obj_info[i], "is_right_mirror_open")) {
  155.       //found_mirror = TRUE;
  156.       sscanf(ply_obj_info[i], "%s%d", temp, &isRightMirrorOpen);
  157.     }
  158.     if (strstr(ply_obj_info[i], "is_linear_scan")) {
  159.       foundScanType = TRUE;
  160.       sscanf(ply_obj_info[i], "%s%d", temp, &isLinearScan);
  161.     }
  162.   }
  163.   min_std = avg_std / RANGE_DATA_SIGMA_FACTOR;
  164.   max_std = avg_std * RANGE_DATA_SIGMA_FACTOR;
  165.   // set up the range data structure
  166.   nlg = num_cols;
  167.   nlt = num_rows;
  168.   intensity = NULL;
  169.   confidence = NULL;
  170.   matDiff = NULL;
  171.   hasColor = 0;
  172.   hasIntensity = 0;
  173.   hasConfidence = 0;
  174.   multConfidence = 0;
  175.   hasTexture = 0;
  176.   ltMin = 0;
  177.   ltMax = nlt-1;
  178.   lgMin = 0;
  179.   lgMax = nlg-1;
  180.   if (!foundScanType) {
  181.     printf("Assumed to be linear scan...n");
  182.     isLinearScan = TRUE;
  183.   }
  184.   if (!is_warped) {
  185.     viewDir.set(0, 0, -1);
  186.   } else {
  187.     if (isRightMirrorOpen) {
  188.       viewDir.set(-sin(30*M_PI/180), 0, -cos(30*M_PI/180));
  189.     } else {
  190.       viewDir.set(sin(30*M_PI/180), 0, -cos(30*M_PI/180));
  191.     }
  192.   }
  193.   num_obj_info = ply_num_obj_info;
  194.   obj_info = new char*[ply_num_obj_info];
  195.   for (i = 0; i < ply_num_obj_info; i++) {
  196.     obj_info[i] = new char[strlen(ply_obj_info[i])+1];
  197.     strcpy(obj_info[i], ply_obj_info[i]);
  198.   }
  199.   // see if we've got both vertex and range_grid data
  200.   plist = ply.get_element_description("vertex", &num_elems, &nprops);
  201.   if (plist == NULL) {
  202.     fprintf (stderr, "file doesn't contain vertex datan");
  203.     return 0;
  204.   }
  205.   numSamples = num_elems;
  206.   plist = ply.get_element_description("range_grid", &num_elems, &nprops);
  207.   if (plist == NULL) {
  208.     fprintf (stderr, "file doesn't contain range_grid datan");
  209.     return 0;
  210.   }
  211.   // read in the range data
  212.   for (i = 0; i < nelems; i++) {
  213.     elem_name = elist[i];
  214.     plist = ply.get_element_description(elem_name, &num_elems, &nprops);
  215.     if (equal_strings ("vertex", elem_name)) {
  216.       // see if the file contains intensities
  217.       for (j = 0; j < nprops; j++) {
  218.         if (equal_strings ("std_dev", plist[j]->name))
  219.           get_std_dev = 1;
  220.         if (equal_strings ("confidence", plist[j]->name))
  221.           get_confidence = 1;
  222.         if (equal_strings ("intensity", plist[j]->name))
  223.           get_intensity = 1;
  224.         if (equal_strings ("diffuse_red", plist[j]->name))
  225.           has_red = 1;
  226.         if (equal_strings ("diffuse_green", plist[j]->name))
  227.           has_green = 1;
  228.         if (equal_strings ("diffuse_blue", plist[j]->name))
  229.           has_blue = 1;
  230.       }
  231.       if (has_red && has_green && has_blue) {
  232.         get_color = 1;
  233.         hasColor = 1;
  234.       }
  235.       if (get_intensity)
  236.         hasIntensity = 1;
  237.       if (get_std_dev && is_warped) {
  238.         hasConfidence = 1;
  239.         multConfidence = 1;
  240.       }
  241.       else if (get_confidence)
  242.         hasConfidence = 1;
  243.       ply.get_property ("vertex", &vert_std_props[0]);
  244.       ply.get_property ("vertex", &vert_std_props[1]);
  245.       ply.get_property ("vertex", &vert_std_props[2]);
  246.       if (get_confidence)     
  247.         ply.get_property ("vertex", &vert_std_props[3]);
  248.       if (get_intensity)             
  249.         ply.get_property ("vertex", &vert_std_props[4]);
  250.       if (get_color) {    
  251.         ply.get_property ("vertex", &vert_std_props[5]);
  252.         ply.get_property ("vertex", &vert_std_props[6]);
  253.         ply.get_property ("vertex", &vert_std_props[7]);
  254.       }
  255.       if (get_std_dev)
  256.         ply.get_property ("vertex", &vert_std_props[8]);
  257.       coords = new Pnt3[numSamples];
  258.       if (get_confidence || get_std_dev)
  259. confidence = new float[numSamples];
  260.       if (get_intensity)
  261. intensity = new float[numSamples];
  262.       if (get_color)
  263. matDiff = new vec3uc[numSamples];
  264.       for (j = 0; j < num_elems; j++) {
  265.         __STL_TRY {
  266.   ply.get_element ((void *) &vert);
  267. }
  268. __STL_CATCH_ALL {
  269.   
  270.   return NULL;
  271. }
  272.         coords[j].set(&vert.x);
  273.         if (get_intensity) {
  274.           intensity[j] = vert.intensity;
  275. }
  276.         if (get_std_dev&&is_warped) {
  277.           std = vert.confidence;
  278.           if (std < min_std)
  279.             conf = 0;
  280.           else if (std < avg_std)
  281.             conf = (std - min_std) / (avg_std - min_std);
  282.           else if (std > max_std)
  283.             conf = 0;
  284.           else
  285.     conf = (max_std - std) / (max_std - avg_std);
  286.   // Unsafe to use vertex intensity, as aperture 
  287.   // settings may change between scans.  
  288.   // Instead, use std_dev confidence * orientation.
  289.   // conf *= vert.intensity;
  290.   if (get_intensity)
  291.     if (vert.intensity < RANGE_DATA_MIN_INTENSITY) conf = 0.0;
  292.           confidence[j] = conf;
  293.         }
  294.         else if (get_confidence) {
  295.           confidence[j] = vert.confidence;
  296.         }
  297.         if (get_color) {
  298.           matDiff[j][0] = vert.red;
  299.           matDiff[j][1] = vert.grn;
  300.           matDiff[j][2] = vert.blu;
  301.         }
  302.       }
  303.     }
  304.     if (equal_strings ("range_grid", elem_name)) {
  305.       indices = new int[nlt * nlg];
  306.       ply.get_element_setup(elem_name, 1, range_props);
  307.       for (j = 0; j < num_elems; j++) {
  308. __STL_TRY {   
  309.   ply.get_element((void *) &range_pnt);
  310. }
  311. __STL_CATCH_ALL {
  312.   return NULL;
  313. }
  314.         if (range_pnt.num_pts == 0)
  315.           indices[j] = -1;
  316.         else {
  317.   max = -FLT_MAX;
  318.   for (k = 0; k < range_pnt.num_pts; k++) {
  319.     index = range_pnt.pts[k];
  320.     // There will only be more than one point per sample
  321.     // if there are intensities
  322.     if (get_intensity) {
  323.       if (intensity[index] > max) {
  324. max = intensity[index];
  325. best_index = index;
  326.       }
  327.     }
  328.     else {
  329.       best_index = index;
  330.     }
  331.   }
  332.   index = best_index;
  333.   if (get_confidence || get_std_dev) {
  334.     if (confidence[index] > 0.0)  
  335.       indices[j] = index;
  336.     else
  337.       indices[j] = -1;
  338.   } else {
  339.     indices[j] = index;
  340.   }
  341.   if (get_intensity) {
  342.     if (intensity[index] < RANGE_DATA_MIN_INTENSITY) {
  343.       indices[j] = -1;
  344.     }
  345.   }
  346.   delete range_pnt.pts;
  347. }
  348.       }
  349.     }
  350.   }
  351.   return 1;
  352. }
  353. /*****************************************************************
  354. Create a triangle mesh from scan data.
  355. Entry:
  356.   sc         - scan data to make into triangle mesh
  357.   level      - level of mesh (how detailed), in [0,1,2,3]
  358.   table_dist - distance for spatial subdivision hash table
  359. Exit:
  360.   returns pointer to newly-created mesh
  361. ******************************************************************/
  362. Mesh *
  363. RangeGrid::toMesh(int subSamp, int hasTexture)
  364. {
  365.   int i,j;
  366.   int ii,jj;
  367.   int in1,in2,in3,in4,vin1,vin2,vin3,vin4;
  368.   int max_tris;
  369.   Mesh *mesh = new Mesh;
  370.   int _ltMin = ltMax - (ltMax/subSamp)*subSamp;
  371.   
  372.   // create a list saying whether a vertex is going to be used
  373.   int *vert_index = new int[numSamples];
  374.   for (i = 0; i < numSamples; i++)
  375.     vert_index[i] = -1;
  376.   // Extra column of vertices for wrap-around
  377.   int *vert_index_extra = new int[nlt];
  378.   for (i = _ltMin; i <= ltMax; i++)
  379.     vert_index_extra[i] = -1;
  380.   // see which vertices will be used in a triangle
  381.   int count = 0;
  382.   for (j = _ltMin; j <= ltMax; j += subSamp) {
  383.     for (i = lgMin; i <= lgMax; i += subSamp) {
  384.       in1 = indices[i + j * nlg];
  385.       if (in1 >= 0) {
  386. vert_index[in1] = 1;
  387. count++;
  388.       }
  389.     }
  390.     if (!isLinearScan) {
  391.       i = lgMin;
  392.       in1 = indices[i + j * nlg];
  393.       if (in1 >= 0) {
  394. vert_index_extra[j] = 1;
  395. count++;
  396.       }
  397.     }
  398.   }
  399.   printf("Num verts = %dn", count);
  400.   if (hasConfidence)
  401.     mesh->vertConfidence = new float[count];
  402.   if (hasTexture)
  403.     mesh->texture = new vec2f[count];
  404.   if (hasIntensity)
  405.     mesh->vertIntensity = new float[count];
  406.   if (matDiff)
  407.     mesh->vertMatDiff = new vec3uc[count];
  408.   max_tris = count * 6;
  409.   mesh->tris.reserve(max_tris);
  410.   // create the vertices
  411.   count = 0;
  412.   for (j = _ltMin; j <= ltMax; j += subSamp) {
  413.     for (i = lgMin; i <= lgMax; i += subSamp) {
  414.       in1 = indices[i + j * nlg];
  415.       if (in1 >= 0) {
  416. vert_index[in1] = count;
  417. mesh->vtx.push_back(coords[in1]);
  418. if (hasConfidence)
  419.   mesh->vertConfidence[count] = confidence[in1];
  420. if (hasIntensity)
  421.   mesh->vertIntensity[count] = intensity[in1];
  422. if (hasColor) {
  423.   mesh->vertMatDiff[count][0] = matDiff[in1][0];
  424.   mesh->vertMatDiff[count][1] = matDiff[in1][1];
  425.   mesh->vertMatDiff[count][2] = matDiff[in1][2];
  426. }
  427. count++;
  428.       }
  429.     }
  430.     if (!isLinearScan) {
  431.       i = lgMin;
  432.       in1 = indices[i + j * nlg];
  433.       if (in1 >= 0) {
  434. vert_index_extra[j] = count;
  435. mesh->vtx.push_back(coords[in1]);
  436. if (hasConfidence)
  437.   mesh->vertConfidence[count] = confidence[in1];
  438. if (hasIntensity)
  439.   mesh->vertIntensity[count] = intensity[in1];
  440. if (hasColor) {
  441.   mesh->vertMatDiff[count][0] = matDiff[in1][0];
  442.   mesh->vertMatDiff[count][1] = matDiff[in1][1];
  443.   mesh->vertMatDiff[count][2] = matDiff[in1][2];
  444. }
  445. count++;
  446.       }
  447.     }
  448.   }
  449.   // Assign texture coordinates
  450.   if (hasTexture) {
  451.     for (j = _ltMin; j <= ltMax; j += subSamp) {
  452.       for (i = lgMin; i <= lgMax; i += subSamp) {
  453. in1 = indices[i + j * nlg];
  454. if (in1 >= 0) {
  455.   vin1 = vert_index[in1];
  456.   mesh->texture[vin1][0] = float(i-lgMin)/(lgMax-lgMin+1);
  457.   mesh->texture[vin1][1] = float(j)/nlt;
  458. }
  459.       }
  460.       if (!isLinearScan) {
  461. i = lgMin;
  462. in1 = indices[i + j * nlg];
  463. if (in1 >= 0) {
  464.   vin1 = vert_index_extra[j];
  465.   mesh->texture[vin1][0] = 1 + 1.0/(lgMax - lgMin + 1);
  466.   mesh->texture[vin1][1] = float(j)/nlt;
  467.   count++;
  468. }
  469.       }
  470.     }
  471.   }
  472.   // create the triangles
  473.   for (j = _ltMin; j <= ltMax - subSamp; j += subSamp) {
  474.     for (i = lgMin; i <= lgMax - subSamp; i += subSamp) {
  475.       ii = (i + subSamp) % nlg;
  476.       jj = (j + subSamp) % nlt;
  477.       // count the number of good vertices
  478.       // 2 3
  479.       // 1 4
  480.       in1 = indices[ i +  j * nlg];
  481.       in2 = indices[ i + jj * nlg];
  482.       in3 = indices[ii + jj * nlg];
  483.       in4 = indices[ii +  j * nlg];
  484.       count = (in1 >= 0) + (in2 >= 0) + (in3 >= 0) + (in4 >=0);
  485.       if (in1 >= 0) {
  486. vin1 = vert_index[in1];
  487.       }
  488.       if (in2 >= 0) {
  489. vin2 = vert_index[in2];
  490.       }
  491.       if (in3 >= 0) {
  492. vin3 = vert_index[in3];
  493.       }
  494.       if (in4 >= 0) {
  495. vin4 = vert_index[in4];
  496.       }
  497.       if (count == 4) { // all 4 vertices okay, so make 2 tris
  498. // compute lengths of cross-edges
  499. float len1 = dist(mesh->vtx[vin1], mesh->vtx[vin3]);
  500. float len2 = dist(mesh->vtx[vin2], mesh->vtx[vin4]);
  501. if (len1 < len2) {
  502.   mesh->addTri(vin2, vin1, vin3);
  503.   mesh->addTri(vin1, vin4, vin3);
  504. } else {
  505.   mesh->addTri(vin2, vin1, vin4);
  506.   mesh->addTri(vin2, vin4, vin3);
  507. }
  508.       }
  509.       else if (count == 3) { // only 3 vertices okay, so make 1 tri
  510. if        (in1 == -1) {
  511.   mesh->addTri(vin2, vin4, vin3);
  512. } else if (in2 == -1) {
  513.   mesh->addTri(vin1, vin4, vin3);
  514. } else if (in3 == -1) {
  515.   mesh->addTri(vin2, vin1, vin4);
  516. } else { // in4 == -1
  517.   mesh->addTri(vin2, vin1, vin3);
  518. }
  519.       }
  520.     }
  521.   }
  522.   
  523.   // Do the wrap around for cylindrical scans
  524.   if (!isLinearScan) {
  525.     ii = lgMin;
  526.     for (j = _ltMin; j <= ltMax - subSamp; j += subSamp) {
  527.       jj = (j + subSamp) % nlt;
  528.       // count the number of good vertices
  529.       in1 = indices[ i +  j * nlg];
  530.       in2 = indices[ i + jj * nlg];
  531.       in3 = indices[ii + jj * nlg];
  532.       in4 = indices[ii +  j * nlg];
  533.       count = (in1 >= 0) + (in2 >= 0) + (in3 >= 0) + (in4 >=0);
  534.       if (in1 >= 0) {
  535. vin1 = vert_index[in1];
  536.       }
  537.       if (in2 >= 0) {
  538. vin2 = vert_index[in2];
  539.       }
  540.       if (in3 >= 0) {
  541. vin3 = vert_index_extra[jj];
  542.       }
  543.       if (in4 >= 0) {
  544. vin4 = vert_index_extra[j];
  545.       }
  546.       if (count == 4) { // all 4 vertices okay, so make 2 tris
  547. // compute lengths of cross-edges
  548. float len1 = dist(mesh->vtx[vin1], mesh->vtx[vin3]);
  549. float len2 = dist(mesh->vtx[vin2], mesh->vtx[vin4]);
  550. if (len1 < len2) {
  551.   mesh->addTri(vin2, vin1, vin3);
  552.   mesh->addTri(vin1, vin4, vin3);
  553. } else {
  554.   mesh->addTri(vin2, vin1, vin4);
  555.   mesh->addTri(vin2, vin4, vin3);
  556. }
  557.       }
  558.       else if (count == 3) { // only 3 vertices okay, so make 1 tri
  559. if        (in1 == -1) {
  560.   mesh->addTri(vin2, vin4, vin3);
  561. } else if (in2 == -1) {
  562.   mesh->addTri(vin1, vin4, vin3);
  563. } else if (in3 == -1) {
  564.   mesh->addTri(vin2, vin1, vin4);
  565. } else { // in4 == -1
  566.   mesh->addTri(vin2, vin1, vin3);
  567. }
  568.       }
  569.     }
  570.   }
  571.   mesh->hasVertNormals = FALSE;
  572.   mesh->initNormals(UseAreaWeightedNormals);
  573.   if (!isLinearScan) {
  574.     for (j = _ltMin; j <= ltMax; j += subSamp) {
  575.       in1 = indices[lgMin + j * nlg];
  576.       if (in1 >= 0) {
  577. vin1 = vert_index[in1];
  578. vin2 = vert_index_extra[j];
  579. mesh->nrm[3*vin1  ] += mesh->nrm[3*vin2  ];
  580. mesh->nrm[3*vin1+1] += mesh->nrm[3*vin2+1];
  581. mesh->nrm[3*vin1+2] += mesh->nrm[3*vin2+2];
  582. Pnt3 temp (mesh->nrm[3*vin1],
  583.    mesh->nrm[3*vin1+1], mesh->nrm[3*vin1+2]);
  584. temp /= 32767;
  585. temp.normalize();
  586. temp *= 32767;
  587. mesh->nrm[3*vin1  ] = mesh->nrm[3*vin2  ] = temp[0];
  588. mesh->nrm[3*vin1+1] = mesh->nrm[3*vin2+1] = temp[1];
  589. mesh->nrm[3*vin1+2] = mesh->nrm[3*vin2+2] = temp[2];
  590.       }
  591.     }
  592.   }
  593.   // free up the vertex index list
  594.   delete [] vert_index;
  595.   delete [] vert_index_extra;
  596.   if (isModelMakerScan) mesh->remove_stepedges(50, 8);
  597.      else mesh->remove_stepedges(50, 4);
  598.   return mesh;
  599. }
  600. void
  601. RangeGrid::addTriangleCheckNormal(Mesh *mesh, 
  602.   int vin1, int vin2, int vin3, 
  603.   Pnt3 &viewDir, float minDot)
  604. {
  605.   float _dot = fabs(dot(viewDir, 
  606. normal(mesh->Vtx(vin1), mesh->Vtx(vin2),
  607.        mesh->Vtx(vin3))));
  608.   int tooGrazing = _dot < minDot;
  609.   if (tooGrazing)
  610.     return;
  611.   mesh->addTri(vin2, vin1, vin3);
  612. }
  613. void
  614. RangeGrid::addTriangleCheckLength(Mesh *mesh, 
  615.   int vin1, int vin2, int vin3, 
  616.   float maxLength)
  617. {
  618.   const Pnt3 &c1 = mesh->Vtx(vin1);
  619.   const Pnt3 &c2 = mesh->Vtx(vin2);
  620.   const Pnt3 &c3 = mesh->Vtx(vin3);
  621.   if (dist(c1,c2) > maxLength)
  622.     return;
  623.   if (dist(c1,c3) > maxLength)
  624.     return;
  625.   if (dist(c2,c3) > maxLength)
  626.     return;
  627.   mesh->addTri(vin2, vin1, vin3);
  628. }
  629. int
  630. RangeGrid::readCyfile(const char *name)
  631. {
  632.   int xx, yy;
  633.   float x, y, z;
  634.   int count;
  635.   long range;
  636.   int fd = open(name, O_RDONLY, 0);
  637.   GSPEC *gs;
  638.   gs = cyread(NULL, fd);
  639.   float lgincr = 1e-6*gs->lgincr;
  640.   float ltincr = 1e-6*gs->ltincr;
  641.   float theta;
  642.   count = 0;
  643.   for (yy = 0;  yy < gs->nlt; yy++) {
  644.     for (xx = 0;  xx < gs->nlg; xx++) {
  645.       range = getr(gs, yy, xx);
  646.       if (range != VOIDGS(gs) ) {
  647. count++;
  648.       }
  649.     }
  650.   }
  651.   numSamples = count;
  652.   isLinearScan = gs->flags & FLAG_CARTESIAN;
  653.   nlg = gs->nlg;
  654.   nlt = gs->nlt;
  655.   coords = new Pnt3[numSamples];
  656.   indices = new int[nlt * nlg];
  657.   viewDir.set(0, 0, -1);
  658.   count = 0;
  659.   int diff;
  660.   int range1, range2;
  661.   if (!isLinearScan) {
  662.     /* For moving targets (like heads), the begin and
  663.        end points will differ noticably.  This is an attempt
  664.        to counteract that motion by shifting the range data
  665.        by an average amount of discrepancy.  A better job
  666.        would be to find a more complex rigid or even
  667.        non-rigid deformation that would match the points. 
  668.        Even better, find new matches iteratively as in Besl
  669.        and McKay. */
  670.     diff = 0;
  671.     for (yy = 0;  yy < gs->nlt; yy++) {
  672.       range1 = getr(gs, yy, 0);
  673.       range2 = getr(gs, yy, gs->nlg-1);
  674.       if (range1 != VOIDGS(gs) && range2 != VOIDGS(gs) ) {
  675. count++;
  676. diff += (range2 - range1);
  677.       }
  678.     }
  679.     diff = int(float(diff)/count);
  680.   }
  681.   count = 0;
  682.   int lg;
  683.   int yymin = 100000;
  684.   int yymax = -1;
  685.   int xxmax = -1;
  686.   int xxmin = 100000;
  687.   for (yy = 0;  yy < gs->nlt; yy++) {
  688.     for (xx = 0;  xx < gs->nlg; xx++) {
  689.       range = getr(gs, yy, xx);
  690.       if (isLinearScan) {
  691. lg = xx;
  692.       } else {
  693. lg = gs->nlg - xx - 1;
  694.       }
  695.       if (range == VOIDGS(gs) ) {
  696. indices[lg + yy*nlg] = -1;
  697.       }
  698.       else {
  699. yymax = yy > yymax ? yy : yymax;
  700. xxmax = lg > xxmax ? lg : xxmax;
  701. yymin = yy < yymin ? yy : yymin;
  702. xxmin = lg < xxmin ? lg : xxmin;
  703. indices[lg + yy*nlg] = count;
  704. y = yy*ltincr;
  705. if (isLinearScan) {
  706.   x = xx*lgincr - (gs->nlg/2) * lgincr;
  707.   z = range*1e-6;
  708. } else {
  709.   //range -= int(diff*float(xx)/gs->nlg);
  710.   theta = xx*lgincr + M_PI;
  711.   x = -range*1e-6*sin(theta);
  712.   z = range*1e-6*cos(theta);     
  713. }
  714. coords[count].set(x,y,z);
  715. count++;
  716.       }
  717.     }
  718.   }    
  719.   if (!isLinearScan) {
  720.     ltMax = yymax;
  721.     lgMax = xxmax;
  722.     ltMin = yymin;
  723.     lgMin = xxmin;
  724.   } else {
  725.     ltMax = gs->nlt-1;
  726.     lgMax = gs->nlg-1;
  727.     ltMin = 0;
  728.     lgMin = 0;
  729.   }
  730.   // To handle color shifts - ack!
  731.   /*
  732.     lgMin++;
  733.     lgMax--;
  734.   */
  735.   cyfree(gs);
  736.   return 1;
  737. }