1 /*************************************************************************
2 * *
3 * Vega FEM Simulation Library Version 3.1 *
4 * *
5 * "distance field" library , Copyright (C) 2007 CMU, 2016 USC *
6 * All rights reserved. *
7 * *
8 * Code author: Hongyi Xu, Jernej Barbic *
9 * http://www.jernejbarbic.com/code *
10 * *
11 * Research: Jernej Barbic, Hongyi Xu, Doug L. James *
12 * *
13 * Funding: National Science Foundation, Link Foundation, *
14 * Zumberge Research and Innovation Fund at USC *
15 * *
16 * This library is free software; you can redistribute it and/or *
17 * modify it under the terms of the BSD-style license that is *
18 * included with this library in the file LICENSE.txt *
19 * *
20 * This library is distributed in the hope that it will be useful, *
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file *
23 * LICENSE.TXT for more details. *
24 * *
25 *************************************************************************/
26
27 /*
28 Narrowband distance field computation.
29 */
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <float.h>
35 #include <fstream>
36 #include <set>
37 #include "triangle.h"
38 #include "boundingBox.h"
39 #include "distanceFieldNarrowBand.h"
40 #include "objMeshOrientable.h"
41 #include "objMeshOctree.h"
42 #include "trilinearInterpolation.h"
43 #include "vegalong.h"
44 using namespace std;
45
GetFilesize(const char * filename)46 vegalong DistanceFieldNarrowBand::GetFilesize(const char *filename)
47 {
48 FILE * f = fopen(filename, "rb"); /* open the file in read only */
49
50 vegalong size = 0;
51 if (fseek(f, 0, SEEK_END) == 0) /* seek was successful */
52 size = ftell(f);
53 fclose(f);
54 return size;
55 }
56
DistanceFieldNarrowBand()57 DistanceFieldNarrowBand::DistanceFieldNarrowBand() : DistanceFieldBase()
58 {
59 gridPointStatus = NULL;
60 signFieldFlooded = 0;
61 }
62
~DistanceFieldNarrowBand()63 DistanceFieldNarrowBand::~DistanceFieldNarrowBand()
64 {
65 free(gridPointStatus);
66 }
67
68 // the routines for signed and unsigned distance field computation
69 #define COMPUTE_SIGNED_FIELD_NARROWBAND
70 #define COMPUTE_INTERIOR_FIELD_NARROWBAND
71 #include "computeFieldNarrowBand.cpp"
72 #undef COMPUTE_INTERIOR_FIELD_NARROWBAND
73 #include "computeFieldNarrowBand.cpp"
74 #undef COMPUTE_SIGNED_FIELD_NARROWBAND
75 #include "computeFieldNarrowBand.cpp"
76
load(const std::string & filename)77 int DistanceFieldNarrowBand::load(const std::string& filename)
78 {
79 ifstream fin(filename.c_str(),ios::binary);
80 if (!fin)
81 return 1;
82
83 fin.read((char*)&resolutionX, sizeof(int));
84
85 // the type of data (single-precision or double-precision) is encoded as the sign of the x-resolution
86 bool floatData = (resolutionX < 0);
87 if (floatData)
88 resolutionX = -resolutionX;
89
90 fin.read((char*)&resolutionY, sizeof(int));
91
92 if (resolutionY < 0) // negative second resolution implies closest point data
93 return 1;
94
95 fin.read((char*)&resolutionZ, sizeof(int));
96
97 vegalong size = (resolutionZ + 1) * (resolutionY + 1) * (resolutionX + 1);
98 gridPointStatus = (char*) realloc (gridPointStatus, sizeof(char) * size);
99 for(vegalong i=0; i<size; i++)
100 gridPointStatus[i] = DistanceFieldNarrowBand::EXTERIOR_UNCOMPUTED;
101
102 fin.read((char*)&(bmin_[0]), sizeof(double));
103 fin.read((char*)&(bmin_[1]), sizeof(double));
104 fin.read((char*)&(bmin_[2]), sizeof(double));
105
106 fin.read((char*)&(bmax_[0]), sizeof(double));
107 fin.read((char*)&(bmax_[1]), sizeof(double));
108 fin.read((char*)&(bmax_[2]), sizeof(double));
109
110 setGridParameters();
111
112 int numGridPoints = 0;
113 fin.read((char*)&numGridPoints, sizeof(int));
114
115 int i, j, k;
116 double * buffer = (double*)malloc(sizeof(double));
117 for(int p = 0; p < numGridPoints; p++)
118 {
119 fin.read((char*)&i, sizeof(int));
120 fin.read((char*)&j, sizeof(int));
121 fin.read((char*)&k, sizeof(int));
122 if (floatData)
123 fin.read((char*)buffer, sizeof(float));
124 else
125 fin.read((char*)buffer, sizeof(double));
126
127 distanceData.insert(pair<gridPoint, float>(gridPoint(i,j,k), *(float*)(buffer)));
128 }
129 free(buffer);
130
131 finalizeGridPointStatus();
132
133 fin.close();
134
135 return 0;
136 }
137
saveToText(const std::string & filename)138 int DistanceFieldNarrowBand::saveToText(const std::string& filename)
139 {
140 FILE * fout = fopen((char*)filename.c_str(), "w");
141 if (!fout)
142 return 1;
143
144 fprintf(fout, "%d\n", resolutionX);
145 fprintf(fout, "%d\n", resolutionY);
146 fprintf(fout, "%d\n", resolutionZ);
147
148 for (map<gridPoint, float>::iterator it = distanceData.begin(); it != distanceData.end(); it++)
149 {
150 gridPoint v = it->first;
151 fprintf(fout, "%d %d %d %G\n", v.first, v.second, v.third, it->second);
152 }
153
154 fclose(fout);
155
156 return 0;
157 }
158
saveToDistanceField(const std::string & filename,bool doublePrecision)159 int DistanceFieldNarrowBand::saveToDistanceField(const std::string& filename, bool doublePrecision)
160 {
161 if (doublePrecision)
162 printf("Error: double precision output is not supported. Using float instead.\n");
163 doublePrecision = false;
164
165 ofstream fout;
166 fout.open(filename.c_str(),ios::binary);
167
168 int data = resolutionX;
169 if (!doublePrecision)
170 data = -data;
171
172 fout.write((char*)&data,sizeof(int));
173 fout.write((char*)&resolutionY,sizeof(int));
174 fout.write((char*)&resolutionZ,sizeof(int));
175
176 fout.write((char*)&(bmin_[0]),sizeof(double));
177 fout.write((char*)&(bmin_[1]),sizeof(double));
178 fout.write((char*)&(bmin_[2]),sizeof(double));
179
180 fout.write((char*)&(bmax_[0]),sizeof(double));
181 fout.write((char*)&(bmax_[1]),sizeof(double));
182 fout.write((char*)&(bmax_[2]),sizeof(double));
183
184 int flag = 1;
185 for(vegalong k=0; k<=resolutionZ; k++)
186 for(vegalong j=0; j<=resolutionY; j++)
187 for(vegalong i=0; i<=resolutionX; i++)
188 {
189 float dist = distance(i,j,k);
190 if (fabs(dist) != FLT_MAX)
191 flag = (dist >= 0) ? 1 : -1;
192 else
193 {
194 if (flag == -1)
195 dist = -FLT_MAX;
196 }
197 fout.write((char*)&dist, sizeof(float));
198 }
199 fout.close();
200
201 return 0;
202 }
203
save(const std::string & filename,bool doublePrecision)204 int DistanceFieldNarrowBand::save(const std::string& filename, bool doublePrecision)
205 {
206 if (doublePrecision)
207 printf("Error: double precision output is not supported. Using float instead.\n");
208 doublePrecision = false;
209
210 ofstream fout;
211 fout.open(filename.c_str(),ios::binary);
212
213 int data = resolutionX;
214 if (!doublePrecision)
215 data = -data;
216
217 fout.write((char*)&data,sizeof(int));
218 fout.write((char*)&resolutionY,sizeof(int));
219 fout.write((char*)&resolutionZ,sizeof(int));
220
221 fout.write((char*)&(bmin_[0]),sizeof(double));
222 fout.write((char*)&(bmin_[1]),sizeof(double));
223 fout.write((char*)&(bmin_[2]),sizeof(double));
224
225 fout.write((char*)&(bmax_[0]),sizeof(double));
226 fout.write((char*)&(bmax_[1]),sizeof(double));
227 fout.write((char*)&(bmax_[2]),sizeof(double));
228
229 vegalong numGridPoints = distanceData.size();
230 fout.write((char*)&(numGridPoints),sizeof(int));
231
232 for (map<gridPoint, float>::iterator it = distanceData.begin(); it != distanceData.end(); it++)
233 {
234 gridPoint v = it->first;
235 fout.write((char*)&(v.first), sizeof(int));
236 fout.write((char*)&(v.second), sizeof(int));
237 fout.write((char*)&(v.third), sizeof(int));
238 float value = it->second;
239 fout.write((char*)&(value), sizeof(float));
240 }
241
242 fout.close();
243
244 return 0;
245 }
246
finalizeGridPointStatus()247 void DistanceFieldNarrowBand::finalizeGridPointStatus()
248 {
249 // assumption: bounding box covers the entire geometry
250
251 int flag = 1;
252 vegalong index = 0;
253 for(vegalong k=0; k<=resolutionZ; k++)
254 for(vegalong j=0; j<=resolutionY; j++)
255 for(vegalong i=0; i<=resolutionX; i++)
256 {
257 float dist = distance(i,j,k);
258 if ((dist == FLT_MAX) || (dist == -FLT_MAX))
259 {
260 gridPointStatus[index] = (flag == -1) ? DistanceFieldNarrowBand::INTERIOR_UNCOMPUTED : DistanceFieldNarrowBand::EXTERIOR_UNCOMPUTED;
261 }
262 else
263 {
264 flag = (dist >= 0) ? 1 : -1;
265 gridPointStatus[index] = DistanceFieldNarrowBand::COMPUTED;
266 }
267
268 index++;
269 }
270 }
271
272 typedef struct
273 {
274 int i,j,k;
275 int di,dj,dk;
276 double fieldDist, gridDist, relError;
277 } errorData;
278
279 struct more_errorData : public std::binary_function< errorData, errorData, bool > {
operator ()more_errorData280 bool operator()(const errorData& x, const errorData& y) {
281 return((x.relError) > (y.relError));
282 }
283 };
284
sanityCheck()285 bool DistanceFieldNarrowBand::sanityCheck()
286 {
287 //double diagonal = sqrt(gridX*gridX + gridY*gridY + gridZ*gridZ);
288
289 bool result = true;
290 int count = 0;
291
292 const int numErrorsPrinted = 3;
293
294 vector<errorData> relErrors;
295 errorData emptyEntry = {0,0,0,0,0,0,0.0,0.0,-1.0};
296 for(int i=0; i<numErrorsPrinted; i++)
297 relErrors.push_back(emptyEntry);
298
299 int counter = 0;
300 for (map<gridPoint, float>::iterator it = distanceData.begin(); it != distanceData.end(); it++)
301 {
302 gridPoint v = it->first;
303 int i = v.first;
304 int j = v.second;
305 int k = v.third;
306
307 float d = it->second;
308 float d1;
309 float sanity;
310 float relError;
311 float fieldDist;
312 float gridDist;
313
314 #define PROCESS(di,dj,dk)\
315 if ((i+(di) <= resolutionX) && (i+(di) >= 0) &&\
316 (j+(dj) <= resolutionY) && (j+(dj) >= 0) &&\
317 (k+(dk) <= resolutionZ) && (k+(dk) >= 0))\
318 {\
319 d1 = distance(i+(di),j+(dj),k+(dk));\
320 if ((d1 != -FLT_MAX) && (d1 != FLT_MAX))\
321 {\
322 gridDist = (float) (len(Vec3d((di)*gridX,(dj)*gridY,(dk)*gridZ)));\
323 fieldDist = fabs(d-d1);\
324 sanity = fieldDist - gridDist;\
325 if (sanity > 1E-6)\
326 {\
327 relError = sanity/gridDist;\
328 if (relError > relErrors[numErrorsPrinted-1].relError)\
329 {\
330 errorData errorEntry = {i,j,k,di,dj,dk,fieldDist,gridDist,relError};\
331 relErrors[numErrorsPrinted-1] = errorEntry;\
332 sort(relErrors.begin(),relErrors.end(),more_errorData());\
333 }\
334 result = false;\
335 count++;\
336 }\
337 }\
338 }
339
340 PROCESS(1,0,0);
341 PROCESS(1,1,0);
342 PROCESS(0,1,0);
343 PROCESS(-1,1,0);
344 PROCESS(-1,0,0);
345 PROCESS(-1,-1,0);
346 PROCESS(0,-1,0);
347 PROCESS(1,-1,0);
348
349 PROCESS(0,0,1);
350 PROCESS(1,0,1);
351 PROCESS(1,1,1);
352 PROCESS(0,1,1);
353 PROCESS(-1,1,1);
354 PROCESS(-1,0,1);
355 PROCESS(-1,-1,1);
356 PROCESS(0,-1,1);
357 PROCESS(1,-1,1);
358
359 PROCESS(0,0,-1);
360 PROCESS(1,0,-1);
361 PROCESS(1,1,-1);
362 PROCESS(0,1,-1);
363 PROCESS(-1,1,-1);
364 PROCESS(-1,0,-1);
365 PROCESS(-1,-1,-1);
366 PROCESS(0,-1,-1);
367 PROCESS(1,-1,-1);
368
369 counter++;
370 if (counter % (resolutionX * resolutionY)== 0)
371 {
372 counter = 0;
373 cout << "." << flush;
374 }
375 }
376
377 cout << endl;
378
379 if (count == 0)
380 cout << "Success: sanity check passed." << endl;
381 else
382 {
383 cout << "Encountered " << count << " possible errors. Largest top " << numErrorsPrinted << " errors (or all errors if fewer):" << endl;
384 for(int i=0; i< (count < numErrorsPrinted ? count : numErrorsPrinted); i++)
385 {
386 errorData * errorEntry = &relErrors[i];
387 float d1 = distance(errorEntry->i,errorEntry->j,errorEntry->k);
388 float d2 = distance(errorEntry->i + errorEntry->di ,errorEntry->j + errorEntry->dj, errorEntry->k + errorEntry->dk);
389 cout << "Distance field change too large. [" << errorEntry->i << "," << errorEntry->j << "," << errorEntry->k << "] to [" << errorEntry->i + (errorEntry->di) << "," << errorEntry->j + (errorEntry->dj) << "," << errorEntry->k + (errorEntry->dk) << "]" << " Dist 1: " << d1 << " Dist 2: " << d2 << " Reported change in distance field: " << errorEntry->fieldDist << " Grid distance: " << errorEntry->gridDist << " Relative error: " << errorEntry->relError << endl;
390 }
391 }
392 return result;
393 }
394
distance(Vec3d pos,int constrainToBox)395 float DistanceFieldNarrowBand::distance(Vec3d pos, int constrainToBox)
396 {
397 // get the index coordinate of the lower-right-bottom corner of the voxel containing 'pos'
398 int i = (int)((pos[0] - bmin_[0]) * invGridX);
399 int j = (int)((pos[1] - bmin_[1]) * invGridY);
400 int k = (int)((pos[2] - bmin_[2]) * invGridZ);
401
402 if (((i<0) || (i>=resolutionX) || (j<0) || (j>=resolutionY) || (k<0) || (k>=resolutionZ)) && (!constrainToBox))
403 {
404 printf("Warning: querying the distance field outside of the bounding box: (i,j,k)=(%d,%d,%d), (x, y, z)=(%lf,%lf,%lf), resolution=(%d,%d,%d)\n",i, j, k, pos[0], pos[1], pos[2], resolutionX, resolutionY, resolutionZ);
405 return FLT_MAX;
406 }
407
408 if (constrainToBox)
409 {
410 if (i >= resolutionX)
411 {
412 i = resolutionX - 1;
413 pos[0] = bmax_[0];
414 }
415
416 if (i < 0)
417 {
418 i = 0;
419 pos[0] = bmin_[0];
420 }
421
422 if (j >= resolutionY)
423 {
424 j = resolutionY - 1;
425 pos[1] = bmax_[1];
426 }
427
428 if (j < 0)
429 {
430 j = 0;
431 pos[1] = bmin_[1];
432 }
433
434 if (k >= resolutionZ)
435 {
436 k = resolutionZ - 1;
437 pos[2] = bmax_[2];
438 }
439
440 if (k < 0)
441 {
442 k = 0;
443 pos[2] = bmin_[2];
444 }
445 }
446
447 float distances[8];
448
449 #define PROCESS2(i,j,k,l)\
450 {\
451 distances[(l)] = distance((i), (j), (k));\
452 if (fabs(distances[(l)]) == FLT_MAX)\
453 {\
454 return distances[(l)];\
455 }\
456 }
457
458 PROCESS2(i,j,k,0);
459 PROCESS2(i+1,j,k,1);
460 PROCESS2(i+1,j+1,k,2);
461 PROCESS2(i,j+1,k,3);
462 PROCESS2(i,j,k+1,4);
463 PROCESS2(i+1,j,k+1,5);
464 PROCESS2(i+1,j+1,k+1,6);
465 PROCESS2(i,j+1,k+1,7);
466
467 double wx,wy,wz;
468 wx = ((pos[0]-bmin_[0]) / gridX) - i;
469 wy = ((pos[1]-bmin_[1]) / gridY) - j;
470 wz = ((pos[2]-bmin_[2]) / gridZ) - k;
471
472 return (float)(TRILINEAR_INTERPOLATION(wx,wy,wz,distances[0],distances[1],distances[2],distances[3],
473 distances[4],distances[5],distances[6],distances[7]));
474 }
475
maxValue()476 float DistanceFieldNarrowBand::maxValue()
477 {
478 float maxValue=-FLT_MAX;
479
480 for(map<gridPoint, float>::iterator it = distanceData.begin(); it != distanceData.end(); it++)
481 {
482 if ((it->second) > maxValue)
483 maxValue = it->second;
484 }
485
486 return maxValue;
487 }
488
minValue()489 float DistanceFieldNarrowBand::minValue()
490 {
491 float minValue=FLT_MAX;
492
493 for(map<gridPoint, float>::iterator it = distanceData.begin(); it != distanceData.end(); it++)
494 {
495 if ((it->second) < minValue)
496 minValue = it->second;
497 }
498
499 return minValue;
500 }
501
maxMinValue(float * maxValue,float * minValue)502 void DistanceFieldNarrowBand::maxMinValue(float* maxValue, float* minValue)
503 {
504 *minValue=FLT_MAX;
505 *maxValue=-FLT_MAX;
506
507 for(map<gridPoint, float>::iterator it = distanceData.begin(); it != distanceData.end(); it++)
508 {
509 float dist = it->second;
510 if (dist < *minValue)
511 *minValue = dist;
512
513 if (dist > *maxValue)
514 *maxValue = dist;
515 }
516 }
517
maxAbsValue()518 float DistanceFieldNarrowBand::maxAbsValue()
519 {
520 float maxValue=0;
521
522 for(map<gridPoint, float>::iterator it = distanceData.begin(); it != distanceData.end(); it++)
523 {
524 float dist = fabs(it->second);
525 if (dist > maxValue)
526 maxValue = dist;
527 }
528
529 return maxValue;
530 }
531
maxNonInftyAbsValue()532 float DistanceFieldNarrowBand::maxNonInftyAbsValue()
533 {
534 float maxValue=0;
535
536 for(map<gridPoint, float>::iterator it = distanceData.begin(); it != distanceData.end(); it++)
537 {
538 float dist = fabs(it->second);
539 if ((dist > maxValue) && (dist != FLT_MAX))
540 maxValue = dist;
541 }
542
543 return maxValue;
544 }
545
maxAbsValue(float threshold)546 float DistanceFieldNarrowBand::maxAbsValue(float threshold)
547 {
548 float maxValue=0;
549
550 for(map<gridPoint, float>::iterator it = distanceData.begin(); it != distanceData.end(); it++)
551 {
552 float dist = fabs(it->second);
553 if ((dist > maxValue) && (dist < threshold))
554 maxValue = dist;
555 }
556
557 return maxValue;
558 }
559
gradient(const Vec3d & pos)560 Vec3d DistanceFieldNarrowBand::gradient(const Vec3d& pos)
561 {
562 int i,j,k;
563
564 // get the indices
565 i = (int)((pos[0] - bmin_[0]) * invGridX);
566 j = (int)((pos[1] - bmin_[1]) * invGridY);
567 k = (int)((pos[2] - bmin_[2]) * invGridZ);
568
569 if ((i<=0) || (i>=resolutionX) || (j<=0) || (j>=resolutionY) || (k<=0) || (k>=resolutionZ))
570 {
571 return Vec3d(0,0,0);
572 }
573
574 double wx,wy,wz;
575 wx = ((pos[0]-bmin_[0]) / gridX) - i;
576 wy = ((pos[1]-bmin_[1]) / gridY) - j;
577 wz = ((pos[2]-bmin_[2]) / gridZ) - k;
578
579 // gradient with respect to trilinear interpolation
580 float distances[8];
581 #define PROCESS3(i,j,k,l)\
582 {\
583 distances[(l)] = distance(i, j, k);\
584 if ((distances[(l)] == FLT_MAX) || (distances[(l)] == -FLT_MAX))\
585 {\
586 return distances[(l)];\
587 }\
588 }
589
590 PROCESS3(i,j,k,0);
591 PROCESS3(i+1,j,k,1);
592 PROCESS3(i+1,j+1,k,2);
593 PROCESS3(i,j+1,k,3);
594 PROCESS3(i,j,k+1,4);
595 PROCESS3(i+1,j,k+1,5);
596 PROCESS3(i+1,j+1,k+1,6);
597 PROCESS3(i,j+1,k+1,7);
598
599 return Vec3d(
600 GRADIENT_COMPONENT_X(wx,wy,wz,distances[0],distances[1],distances[2],distances[3],distances[4],distances[5],distances[6],distances[7]),
601 GRADIENT_COMPONENT_Y(wx,wy,wz,distances[0],distances[1],distances[2],distances[3],distances[4],distances[5],distances[6],distances[7]),
602 GRADIENT_COMPONENT_Z(wx,wy,wz,distances[0],distances[1],distances[2],distances[3],distances[4],distances[5],distances[6],distances[7]) );
603
604 }
605
findSurfaceGridPoints(ObjMesh * objMeshIn)606 void DistanceFieldNarrowBand::findSurfaceGridPoints(ObjMesh* objMeshIn)
607 {
608 ObjMesh objMesh(*objMeshIn);
609
610 surfaceGridPoints.clear();
611 //typedef triple<int,int,int> gridPoint;
612
613 std::set<gridPoint> checkedGridPoints;
614 std::vector<gridPoint> scheduledGridPoints;
615
616 for(unsigned int i=0; i < objMesh.getNumGroups(); ++i)
617 {
618 const ObjMesh::Group * group = objMesh.getGroupHandle(i);
619
620 for (unsigned int j=0; j<group->getNumFaces(); ++j)
621 {
622 Vec3d p0 = objMesh.getPosition(group->getFace(j).getVertex(0).getPositionIndex());
623 Vec3d p1 = objMesh.getPosition(group->getFace(j).getVertex(1).getPositionIndex());
624 Vec3d p2 = objMesh.getPosition(group->getFace(j).getVertex(2).getPositionIndex());
625
626 TriangleBasic triangle(p0,p1,p2);
627
628 Vec3d center = 1.0/3 * (p0 + p1 + p2);
629 Vec3d recCenter = center - bmin_;
630
631 int vi,vj,vk;
632
633 vi = (int)(recCenter[0] / gridX);
634 vj = (int)(recCenter[1] / gridY);
635 vk = (int)(recCenter[2] / gridZ);
636
637 checkedGridPoints.clear();
638 checkedGridPoints.insert(gridPoint(vi, vj, vk));
639
640 scheduledGridPoints.clear();
641 scheduledGridPoints.push_back(gridPoint(vi,vj,vk));
642
643 while (!scheduledGridPoints.empty())
644 {
645 gridPoint v = scheduledGridPoints.back();
646 scheduledGridPoints.pop_back();
647
648 Vec3d bbmin = bmin_ + Vec3d(v.first * gridX, v.second * gridY, v.third * gridZ);
649 Vec3d bbmax = bbmin + Vec3d(gridX, gridY, gridZ);
650
651 BoundingBox bbox(bbmin, bbmax);
652
653 if (triangle.doesIntersectBox(bbox))
654 {
655 //surfaceVoxels.insert(v);
656 //floodFillTag[(v.third * (resolutionY+1) + v.second) * (resolutionX + 1) + v.first] = 1;
657
658 gridPoint neighbor;
659 vegalong index;
660 #define TAGNEIGHBOR(ii,jj,kk)\
661 neighbor = gridPoint(v.first+(ii), v.second+(jj), v.third+(kk));\
662 if ((neighbor.first <= resolutionX) &&\
663 (neighbor.second <= resolutionY) &&\
664 (neighbor.third <= resolutionZ))\
665 {\
666 index = (neighbor.third * (resolutionY+1) + neighbor.second) * (resolutionX + 1) + neighbor.first;\
667 surfaceGridPoints.push_back(index);\
668 }
669
670 for (int iii=0; iii<=1; ++iii)
671 for (int jjj=0; jjj<=1; ++jjj)
672 for (int kkk=0; kkk<=1; ++kkk)
673 {
674 TAGNEIGHBOR(iii, jjj, kkk);
675 }
676
677
678 #define CHECKNEIGHBOR(ii,jj,kk)\
679 neighbor = gridPoint(v.first+(ii), v.second+(jj), v.third+(kk));\
680 if ((neighbor.first >= 0) && (neighbor.first <= resolutionX) &&\
681 (neighbor.second >= 0) && (neighbor.second <= resolutionY) &&\
682 (neighbor.third >= 0) && (neighbor.third <= resolutionZ))\
683 {\
684 if (checkedGridPoints.find(neighbor) == checkedGridPoints.end())\
685 {\
686 checkedGridPoints.insert(neighbor);\
687 scheduledGridPoints.push_back(neighbor);\
688 }\
689 }
690
691 for (int iii=-1; iii<=1; ++iii)
692 for (int jjj=-1; jjj<=1; ++jjj)
693 for (int kkk=-1; kkk<=1; ++kkk)
694 {
695 if ((iii == 0) && (jjj == 0) && (kkk == 0))
696 continue;
697
698 CHECKNEIGHBOR(iii, jjj, kkk);
699 }
700 }
701 }
702 }
703 }
704 }
705
offsetDistanceField(double offset)706 void DistanceFieldNarrowBand::offsetDistanceField(double offset)
707 {
708 for(std::map<gridPoint, float>::iterator it = distanceData.begin(); it != distanceData.end(); it++)
709 it->second += (float) offset;
710 }
711
712