$search
00001 /* 00002 Szymon Rusinkiewicz 00003 Stanford Graphics Lab 00004 00005 trimesh.cc 00006 Computation of connectivity information (e.g. neighbors) for trimeshes. 00007 */ 00008 00009 #include <stdio.h> 00010 #include <limits.h> 00011 #include <float.h> 00012 #include "triutil.h" 00013 #include "trimesh.h" 00014 #include <algorithm> 00015 using std::nth_element; 00016 00017 00018 #define BIGNUM FLT_MAX 00019 #define BIGINT INT_MAX 00020 00021 namespace trimesh { 00022 00023 // Compute a list of the neighboring vertices of each vertex 00024 void TriMesh::FindNeighbors() 00025 { 00026 need_faces(); 00027 00028 printf("Computing lists of neighbors... "); fflush(stdout); 00029 00030 // Step I - compute a first stab at numneighbors, so we know 00031 // how much mem to allocate. 00032 // Overestimates by a factor of 2... 00033 if (!numneighbors) 00034 numneighbors = new int[numvertices]; 00035 memset(numneighbors, 0, numvertices*sizeof(int)); 00036 00037 for (int i=0; i < numfaces; i++) { 00038 numneighbors[faces[i][0]] += 2; 00039 numneighbors[faces[i][1]] += 2; 00040 numneighbors[faces[i][2]] += 2; 00041 } 00042 00043 // OK, Step II - compute the actual neighbors... 00044 if (neighbors) { 00045 for (int i=0; i < numvertices; i++) 00046 delete [] neighbors[i]; 00047 delete [] neighbors; 00048 } 00049 00050 neighbors = new neighborlist[numvertices]; 00051 for (int i=0; i < numvertices; i++) { 00052 neighbors[i] = new int[numneighbors[i]]; 00053 for (int j=0; j < numneighbors[i]; j++) 00054 neighbors[i][j] = numvertices; 00055 } 00056 00057 memset(numneighbors, 0, numvertices*sizeof(int)); 00058 00059 for (int i=0; i < numfaces; i++) { 00060 for (int j=0; j < 3; j++) { 00061 int me, n1, n2, *p; 00062 me = faces[i][j]; 00063 p = neighbors[me]; 00064 n1 = faces[i][(j+1)%3]; 00065 n2 = faces[i][(j+2)%3]; 00066 while ((*p != numvertices) && (*p != n1)) 00067 p++; 00068 if (*p != n1) { 00069 *p = n1; 00070 numneighbors[me]++; 00071 } 00072 p = neighbors[me]; 00073 while ((*p != numvertices) && (*p != n2)) 00074 p++; 00075 if (*p != n2) { 00076 *p = n2; 00077 numneighbors[me]++; 00078 } 00079 } 00080 } 00081 00082 // Compute {min|max}neighbors... 00083 maxneighbors = 0; 00084 minneighbors = BIGINT; 00085 for (int i=0; i < numvertices; i++) { 00086 minneighbors = min(minneighbors, numneighbors[i]); 00087 maxneighbors = max(maxneighbors, numneighbors[i]); 00088 } 00089 00090 printf("Done.\n"); 00091 } 00092 00093 00094 // For each vertex, figure out which faces contain that vertex 00095 void TriMesh::FindAdjacentFaces() 00096 { 00097 need_faces(); 00098 00099 printf("Computing vertex-to-triangle mappings... "); fflush(stdout); 00100 00101 // Step I - compute numadjacentfaces 00102 if (!numadjacentfaces) 00103 numadjacentfaces = new int[numvertices]; 00104 memset(numadjacentfaces, 0, numvertices*sizeof(int)); 00105 00106 for (int i=0; i < numfaces; i++) { 00107 numadjacentfaces[faces[i][0]]++; 00108 numadjacentfaces[faces[i][1]]++; 00109 numadjacentfaces[faces[i][2]]++; 00110 } 00111 00112 // Step II - compute the actual vertex->tri lists... 00113 if (adjacentfaces) { 00114 for (int i=0; i < numvertices; i++) 00115 delete [] adjacentfaces[i]; 00116 delete [] adjacentfaces; 00117 } 00118 00119 maxadjacentfaces = 0; 00120 minadjacentfaces = BIGINT; 00121 00122 adjacentfaces = new adjacentfacelist[numvertices]; 00123 for (int i=0; i < numvertices; i++) { 00124 adjacentfaces[i] = new int[numadjacentfaces[i]]; 00125 for (int j=0; j<numadjacentfaces[i]; j++) 00126 adjacentfaces[i][j] = numfaces; 00127 minadjacentfaces = min(minadjacentfaces, numadjacentfaces[i]); 00128 maxadjacentfaces = max(maxadjacentfaces, numadjacentfaces[i]); 00129 } 00130 00131 for (int i=0; i < numfaces; i++) { 00132 int *p = adjacentfaces[faces[i][0]]; 00133 while (*p != numfaces) 00134 p++; 00135 *p = i; 00136 p = adjacentfaces[faces[i][1]]; 00137 while (*p != numfaces) 00138 p++; 00139 *p = i; 00140 p = adjacentfaces[faces[i][2]]; 00141 while (*p != numfaces) 00142 p++; 00143 *p = i; 00144 } 00145 00146 printf("Done.\n"); 00147 } 00148 00149 00150 // Find the minimum edge length in the mesh 00151 float TriMesh::minedgelength() 00152 { 00153 need_faces(); 00154 if (!numfaces) 00155 return 0; 00156 00157 float min_len = BIGNUM; 00158 for (int i=0; i < numfaces; i++) { 00159 min_len = min(min_len, Dist(vertices[faces[i][0]], 00160 vertices[faces[i][1]])); 00161 min_len = min(min_len, Dist(vertices[faces[i][1]], 00162 vertices[faces[i][2]])); 00163 min_len = min(min_len, Dist(vertices[faces[i][2]], 00164 vertices[faces[i][0]])); 00165 } 00166 00167 return min_len; 00168 } 00169 00170 00171 // Find the maximum edge length in the mesh 00172 float TriMesh::maxedgelength() 00173 { 00174 need_faces(); 00175 if (!numfaces) 00176 return 0; 00177 00178 float max_len = -BIGNUM; 00179 for (int i=0; i < numfaces; i++) { 00180 max_len = max(max_len, Dist(vertices[faces[i][0]], 00181 vertices[faces[i][1]])); 00182 max_len = max(max_len, Dist(vertices[faces[i][1]], 00183 vertices[faces[i][2]])); 00184 max_len = max(max_len, Dist(vertices[faces[i][2]], 00185 vertices[faces[i][0]])); 00186 } 00187 00188 return max_len; 00189 } 00190 00191 00192 // Find the RMS edge length in the mesh. If random_sample is true, 00193 // uses at most 10000 edges (randomly sampled) 00194 float TriMesh::rmsedgelength(bool random_sample /* = true */) 00195 { 00196 need_faces(); 00197 if (!numfaces) 00198 return 0; 00199 00200 if (numfaces <= 3333) 00201 random_sample = false; 00202 int n = random_sample ? 3333 : numfaces; 00203 00204 float rms_len = 0; 00205 for (int i=0; i < n; i++) { 00206 int which = random_sample ? int(numfaces * drand48()) : i; 00207 rms_len += Dist2(vertices[faces[which][0]], 00208 vertices[faces[which][1]]); 00209 rms_len += Dist2(vertices[faces[which][1]], 00210 vertices[faces[which][2]]); 00211 rms_len += Dist2(vertices[faces[which][2]], 00212 vertices[faces[which][0]]); 00213 } 00214 00215 return sqrt(rms_len / (3 * n)); 00216 } 00217 00218 00219 // Find the mean edge length in the mesh. If random_sample is true, 00220 // uses at most 10000 edges (randomly sampled) 00221 float TriMesh::meanedgelength(bool random_sample /* = true */) 00222 { 00223 need_faces(); 00224 if (!numfaces) 00225 return 0; 00226 00227 if (numfaces <= 3333) 00228 random_sample = false; 00229 int n = random_sample ? 3333 : numfaces; 00230 00231 float mean_len = 0; 00232 for (int i=0; i < n; i++) { 00233 int which = random_sample ? int(numfaces * drand48()) : i; 00234 mean_len += Dist(vertices[faces[which][0]], 00235 vertices[faces[which][1]]); 00236 mean_len += Dist(vertices[faces[which][1]], 00237 vertices[faces[which][2]]); 00238 mean_len += Dist(vertices[faces[which][2]], 00239 vertices[faces[which][0]]); 00240 } 00241 00242 return mean_len / (3 * n); 00243 } 00244 00245 00246 // Find the median edge length in the mesh. If random_sample is true, 00247 // uses at most 10000 edges (randomly sampled) 00248 float TriMesh::medianedgelength(bool random_sample /* = true */) 00249 { 00250 need_faces(); 00251 if (!numfaces) 00252 return 0; 00253 00254 if (numfaces <= 3333) 00255 random_sample = false; 00256 int n = random_sample ? 3333 : numfaces; 00257 00258 vector<float> lengths; 00259 lengths.reserve(3*n); 00260 00261 for (int i=0; i < n; i++) { 00262 int which = (numfaces > 3333) ? int(numfaces * drand48()) : i; 00263 lengths.push_back(Dist(vertices[faces[which][0]], 00264 vertices[faces[which][1]])); 00265 lengths.push_back(Dist(vertices[faces[which][1]], 00266 vertices[faces[which][2]])); 00267 lengths.push_back(Dist(vertices[faces[which][2]], 00268 vertices[faces[which][0]])); 00269 } 00270 00271 size_t pos = 3*n/2; 00272 nth_element(lengths.begin(), lengths.begin() + pos, lengths.end()); 00273 return lengths[n/2]; 00274 } 00275 00276 } // namespace trimesh 00277