1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImplicitModeller.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkImplicitModeller.h"
16 
17 #include "vtkCell.h"
18 #include "vtkCellLocator.h"
19 #include "vtkClipPolyData.h"
20 #include "vtkCommand.h"
21 #include "vtkFloatArray.h"
22 #include "vtkGenericCell.h"
23 #include "vtkImageData.h"
24 #include "vtkImageIterator.h"
25 #include "vtkImageProgressIterator.h"
26 #include "vtkInformation.h"
27 #include "vtkInformationVector.h"
28 #include "vtkMath.h"
29 #include "vtkMultiThreader.h"
30 #include "vtkObjectFactory.h"
31 #include "vtkPlane.h"
32 #include "vtkPointData.h"
33 #include "vtkPolyData.h"
34 #include "vtkRectilinearGrid.h"
35 #include "vtkStreamingDemandDrivenPipeline.h"
36 #include "vtkStructuredGrid.h"
37 #include "vtkUnstructuredGrid.h"
38 
39 #include <cmath>
40 
41 vtkStandardNewMacro(vtkImplicitModeller);
42 
43 struct vtkImplicitModellerAppendInfo
44 {
45   vtkImplicitModeller* Modeller;
46   vtkDataSet** Input;
47   double MaximumDistance;
48 };
49 
50 //------------------------------------------------------------------------------
51 // Construct with sample dimensions=(50,50,50), and so that model bounds are
52 // automatically computed from the input. Capping is turned on with CapValue
53 // equal to a large positive number.
vtkImplicitModeller()54 vtkImplicitModeller::vtkImplicitModeller()
55 {
56   this->MaximumDistance = 0.1;
57 
58   this->ModelBounds[0] = 0.0;
59   this->ModelBounds[1] = 0.0;
60   this->ModelBounds[2] = 0.0;
61   this->ModelBounds[3] = 0.0;
62   this->ModelBounds[4] = 0.0;
63   this->ModelBounds[5] = 0.0;
64   this->BoundsComputed = 0;
65 
66   this->SampleDimensions[0] = 50;
67   this->SampleDimensions[1] = 50;
68   this->SampleDimensions[2] = 50;
69 
70   this->Capping = 1;
71   this->OutputScalarType = VTK_FLOAT;
72   this->CapValue = this->GetScalarTypeMax(this->OutputScalarType);
73   this->ScaleToMaximumDistance = 0; // only used for non-float output type
74 
75   this->DataAppended = 0;
76   this->AdjustBounds = 1;
77   this->AdjustDistance = 0.0125;
78 
79   this->ProcessMode = VTK_CELL_MODE;
80   this->LocatorMaxLevel = 5;
81 
82   this->Threader = vtkMultiThreader::New();
83   this->NumberOfThreads = this->Threader->GetNumberOfThreads();
84 }
85 
~vtkImplicitModeller()86 vtkImplicitModeller::~vtkImplicitModeller()
87 {
88   if (this->Threader)
89   {
90     this->Threader->Delete();
91   }
92 }
93 
SetOutputScalarType(int type)94 void vtkImplicitModeller::SetOutputScalarType(int type)
95 {
96   double scalarMax;
97 
98   vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting OutputScalarType to "
99                 << type);
100 
101   scalarMax = this->GetScalarTypeMax(type);
102   if (scalarMax) // legal type
103   {
104     int modified = 0;
105     if (this->CapValue != scalarMax)
106     {
107       this->CapValue = scalarMax;
108       modified = 1;
109     }
110     if (this->OutputScalarType != type)
111     {
112       this->OutputScalarType = type;
113       modified = 1;
114     }
115     if (modified)
116     {
117       this->Modified();
118     }
119   }
120 }
121 
SetCapValue(double value)122 void vtkImplicitModeller::SetCapValue(double value)
123 {
124   vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting CapValue to " << value);
125   // clamp to between 0 and max for scalar type
126   double max = this->GetScalarTypeMax(this->OutputScalarType);
127   if (this->CapValue != (value < 0 ? 0 : (value > max ? max : value)))
128   {
129     this->CapValue = (value < 0 ? 0 : (value > max ? max : value));
130     this->Modified();
131   }
132 }
133 
GetScalarTypeMax(int type)134 double vtkImplicitModeller::GetScalarTypeMax(int type)
135 {
136   switch (type)
137   {
138     case VTK_UNSIGNED_CHAR:
139       return (double)VTK_UNSIGNED_CHAR_MAX;
140     case VTK_CHAR:
141       return (double)VTK_CHAR_MAX;
142     case VTK_UNSIGNED_SHORT:
143       return (double)VTK_UNSIGNED_SHORT_MAX;
144     case VTK_SHORT:
145       return (double)VTK_SHORT_MAX;
146     case VTK_UNSIGNED_INT:
147       return (double)VTK_UNSIGNED_INT_MAX;
148     case VTK_INT:
149       return (double)VTK_INT_MAX;
150     case VTK_UNSIGNED_LONG:
151       return (double)VTK_UNSIGNED_LONG_MAX;
152     case VTK_LONG:
153       return (double)VTK_LONG_MAX;
154     case VTK_FLOAT:
155       return (double)VTK_FLOAT_MAX;
156     case VTK_DOUBLE:
157       return (double)VTK_DOUBLE_MAX;
158     default:
159       return 0;
160   }
161 }
162 
163 //------------------------------------------------------------------------------
164 // Initialize the filter for appending data. You must invoke the
165 // StartAppend() method before doing successive Appends(). It's also a
166 // good idea to manually specify the model bounds; otherwise the input
167 // bounds for the data will be used.
StartAppend()168 void vtkImplicitModeller::StartAppend()
169 {
170   this->StartAppend(0);
171 }
172 
StartAppend(int internal)173 void vtkImplicitModeller::StartAppend(int internal)
174 {
175   vtkIdType numPts;
176   vtkIdType i;
177   double maxDistance;
178 
179   if (!internal)
180   {
181     // we must call update information because we can't be sure that
182     // it has been called.
183     this->UpdateInformation();
184   }
185   vtkInformation* outInfo = this->GetOutputInformation(0);
186   outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
187     vtkStreamingDemandDrivenPipeline::GetWholeExtent(outInfo), 6);
188 
189   vtkDebugMacro(<< "Initializing data");
190   this->AllocateOutputData(this->GetOutput(), this->GetOutputInformation(0));
191   this->UpdateProgress(0.0);
192   this->DataAppended = 1;
193 
194   numPts = this->SampleDimensions[0] * this->SampleDimensions[1] * this->SampleDimensions[2];
195 
196   // initialize output to CapValue at each location
197   maxDistance = this->CapValue;
198   vtkDataArray* newScalars = this->GetOutput()->GetPointData()->GetScalars();
199   for (i = 0; i < numPts; i++)
200   {
201     newScalars->SetComponent(i, 0, maxDistance);
202   }
203 }
204 
205 template <class OT>
SetOutputDistance(double distance,OT * outputValue,double capValue,double scaleFactor)206 void SetOutputDistance(double distance, OT* outputValue, double capValue, double scaleFactor)
207 {
208   // for now, just doing "normal" cast... could consider doing round?
209   if (scaleFactor) // need to scale the distance
210   {
211     *outputValue = static_cast<OT>(distance * scaleFactor);
212   }
213   else
214   {
215     if (capValue && distance > capValue) // clamping iff non-float type
216     {
217       distance = capValue;
218     }
219     *outputValue = static_cast<OT>(distance);
220   }
221 }
222 
223 // Convert distance as stored in output (could be scaled and/or non-double
224 // type) to double distance with correct scaling
225 template <class OT>
ConvertToDoubleDistance(const OT & inDistance,double & distance,double & distance2,double scaleFactor)226 void ConvertToDoubleDistance(
227   const OT& inDistance, double& distance, double& distance2, double scaleFactor)
228 {
229   if (scaleFactor)
230   {
231     distance = inDistance * scaleFactor;
232   }
233   else
234   {
235     distance = inDistance;
236   }
237   distance2 = distance * distance;
238 }
239 
240 //------------------------------------------------------------------------------
241 // Templated append for VTK_VOXEL_MODE process mode and any type of output data
242 template <class OT>
vtkImplicitModellerAppendExecute(vtkImplicitModeller * self,vtkDataSet * input,vtkImageData * outData,int outExt[6],double maxDistance,vtkCellLocator * locator,int id,OT *)243 void vtkImplicitModellerAppendExecute(vtkImplicitModeller* self, vtkDataSet* input,
244   vtkImageData* outData, int outExt[6], double maxDistance, vtkCellLocator* locator, int id, OT*)
245 {
246   int i, j, k;
247   int subId;
248   vtkIdType cellId;
249   double pcoords[3];
250   double *spacing, *origin;
251   double maxDistance2 = maxDistance * maxDistance;
252   double x[3], prevDistance, prevDistance2, distance2, betterDistance;
253   double closestPoint[3], mDist;
254 
255   // allocate weights for the EvaluatePosition
256   double* weights = new double[input->GetMaxCellSize()];
257 
258   // Traverse each voxel; using CellLocator to find the closest point
259   vtkGenericCell* cell = vtkGenericCell::New();
260 
261   spacing = outData->GetSpacing();
262   origin = outData->GetOrigin();
263 
264   vtkImageProgressIterator<OT> outIt(outData, outExt, self, id);
265 
266   // so we know how to scale if desired
267   double scaleFactor = 0;         // 0 used to indicate not scaling
268   double toDoubleScaleFactor = 0; // 0 used to indicate not scaling
269   double capValue = 0;            // 0 used to indicate not clamping (float or double)
270   if (self->GetOutputScalarType() != VTK_FLOAT && self->GetOutputScalarType() != VTK_DOUBLE)
271   {
272     capValue = self->GetCapValue();
273     if (self->GetScaleToMaximumDistance())
274     {
275       scaleFactor = capValue / maxDistance;
276       toDoubleScaleFactor = maxDistance / capValue;
277     }
278   }
279 
280   int testIndex = 0;
281   for (k = outExt[4]; k <= outExt[5]; k++)
282   {
283     x[2] = spacing[2] * k + origin[2];
284     for (j = outExt[2]; j <= outExt[3]; j++)
285     {
286       cellId = -1;
287       x[1] = spacing[1] * j + origin[1];
288       OT* outSI = outIt.BeginSpan();
289       for (i = outExt[0]; i <= outExt[1]; i++, testIndex++)
290       {
291         x[0] = spacing[0] * i + origin[0];
292         ConvertToDoubleDistance(*outSI, prevDistance, prevDistance2, toDoubleScaleFactor);
293         betterDistance = -1;
294 
295         if (cellId != -1)
296         {
297           cell->EvaluatePosition(x, closestPoint, subId, pcoords, distance2, weights);
298           if (distance2 <= maxDistance2 && distance2 < prevDistance2)
299           {
300             mDist = sqrt(distance2);
301             betterDistance = mDist;
302           }
303           else if (prevDistance2 < maxDistance2)
304           {
305             mDist = prevDistance;
306           }
307           else
308           {
309             mDist = maxDistance;
310           }
311         }
312         else if (prevDistance2 < maxDistance2)
313         {
314           mDist = prevDistance;
315         }
316         else
317         {
318           mDist = maxDistance;
319         }
320 
321         if (locator->FindClosestPointWithinRadius(
322               x, mDist, closestPoint, cell, cellId, subId, distance2))
323         {
324           if (distance2 <= prevDistance2)
325           {
326             betterDistance = sqrt(distance2);
327           }
328         }
329         else
330         {
331           cellId = -1;
332         }
333 
334         if (betterDistance != -1)
335         {
336           SetOutputDistance(betterDistance, outSI, capValue, scaleFactor);
337         }
338 
339         outSI++;
340       }
341       outIt.NextSpan();
342     }
343   }
344   cell->Delete();
345   delete[] weights;
346 }
347 
348 //------------------------------------------------------------------------------
349 // This is the multithreaded piece of the append when doing per voxel
350 // processing - it is called once for each thread, with each thread
351 // taking a different slab of the output to work on.  The actual work is done
352 // in vtkImplicitModellerAppendExecute; here we just setup for the per voxel
353 // processing.
vtkImplicitModeller_ThreadedAppend(void * arg)354 static VTK_THREAD_RETURN_TYPE vtkImplicitModeller_ThreadedAppend(void* arg)
355 {
356   int threadCount;
357   int threadId;
358   vtkImplicitModellerAppendInfo* userData;
359   vtkImageData* output;
360   double maxDistance;
361   int i;
362   double adjBounds[6];
363   double* spacing;
364   double* origin;
365   int slabSize, slabMin, slabMax;
366   int outExt[6];
367 
368   threadId = ((vtkMultiThreader::ThreadInfo*)(arg))->ThreadID;
369   threadCount = ((vtkMultiThreader::ThreadInfo*)(arg))->NumberOfThreads;
370   userData = (vtkImplicitModellerAppendInfo*)(((vtkMultiThreader::ThreadInfo*)(arg))->UserData);
371 
372   if (userData->Input[threadId] == nullptr)
373   {
374     return VTK_THREAD_RETURN_VALUE;
375   }
376 
377   maxDistance = userData->MaximumDistance;
378 
379   output = userData->Modeller->GetOutput();
380   spacing = output->GetSpacing();
381   origin = output->GetOrigin();
382 
383   int* sampleDimensions = userData->Modeller->GetSampleDimensions();
384   if (!output->GetPointData()->GetScalars())
385   {
386     vtkGenericWarningMacro("Sanity check failed.");
387     return VTK_THREAD_RETURN_VALUE;
388   }
389 
390   // break up into slabs based on threadId and threadCount
391   slabSize = sampleDimensions[2] / threadCount;
392   if (slabSize == 0) // in case threadCount >  sampleDimensions[2]
393   {
394     slabSize = 1;
395   }
396   slabMin = threadId * slabSize;
397   if (slabMin >= sampleDimensions[2])
398   {
399     return VTK_THREAD_RETURN_VALUE;
400   }
401   slabMax = slabMin + slabSize - 1;
402   if (threadId == threadCount - 1)
403   {
404     slabMax = sampleDimensions[2] - 1;
405   }
406 
407   const double* bounds = userData->Input[threadId]->GetBounds();
408   for (i = 0; i < 3; i++)
409   {
410     adjBounds[2 * i] = bounds[2 * i] - maxDistance;
411     adjBounds[2 * i + 1] = bounds[2 * i + 1] + maxDistance;
412   }
413 
414   // compute dimensional bounds in data set
415   for (i = 0; i < 3; i++)
416   {
417     outExt[i * 2] = (int)((double)(adjBounds[2 * i] - origin[i]) / spacing[i]);
418     outExt[i * 2 + 1] = (int)((double)(adjBounds[2 * i + 1] - origin[i]) / spacing[i]);
419     if (outExt[i * 2] < 0)
420     {
421       outExt[i * 2] = 0;
422     }
423     if (outExt[i * 2 + 1] >= sampleDimensions[i])
424     {
425       outExt[i * 2 + 1] = sampleDimensions[i] - 1;
426     }
427   }
428 
429   // input not close enough to effect this slab
430   if (outExt[4] > slabMax || outExt[5] < slabMin)
431   {
432     return VTK_THREAD_RETURN_VALUE;
433   }
434 
435   // adjust min/max to match slab
436   if (outExt[4] < slabMin)
437   {
438     outExt[4] = slabMin;
439   }
440   if (outExt[5] > slabMax)
441   {
442     outExt[5] = slabMax;
443   }
444 
445   vtkCellLocator* locator = vtkCellLocator::New();
446 
447   // Set up the cell locator.
448   // If AutomaticOff, then NumberOfCellsPerBucket only used for allocating
449   // memory.  If AutomaticOn, then NumberOfCellsPerBucket is used to guess
450   // the depth for the uniform octree required to support
451   // NumberOfCellsPerBucket (assuming uniform distribution of cells).
452   locator->SetDataSet(userData->Input[threadId]);
453   locator->AutomaticOff();
454   locator->SetMaxLevel(userData->Modeller->GetLocatorMaxLevel());
455   locator->SetNumberOfCellsPerBucket(1);
456   locator->CacheCellBoundsOn();
457   locator->BuildLocator();
458 
459   switch (userData->Modeller->GetOutputScalarType())
460   {
461     vtkTemplateMacro(vtkImplicitModellerAppendExecute(userData->Modeller, userData->Input[threadId],
462       output, outExt, userData->MaximumDistance, locator, threadId, static_cast<VTK_TT*>(nullptr)));
463     default:
464       vtkGenericWarningMacro("Execute: Unknown output ScalarType");
465       return VTK_THREAD_RETURN_VALUE;
466   }
467 
468   locator->Delete();
469   return VTK_THREAD_RETURN_VALUE;
470 }
471 
472 //------------------------------------------------------------------------------
473 // Templated append for VTK_CELL_MODE process mode and any type of output data
474 template <class OT>
vtkImplicitModellerAppendExecute(vtkImplicitModeller * self,vtkDataSet * input,vtkImageData * outData,double maxDistance,OT *)475 void vtkImplicitModellerAppendExecute(
476   vtkImplicitModeller* self, vtkDataSet* input, vtkImageData* outData, double maxDistance, OT*)
477 {
478   int i, j, k, updateTime;
479   vtkIdType cellNum;
480   double adjBounds[6];
481   double pcoords[3];
482   int outExt[6];
483   double x[3], prevDistance2, distance, distance2;
484   int subId;
485   double closestPoint[3];
486   double* weights = new double[input->GetMaxCellSize()];
487   double maxDistance2;
488   double *spacing, *origin;
489 
490   spacing = outData->GetSpacing();
491   origin = outData->GetOrigin();
492 
493   maxDistance2 = maxDistance * maxDistance;
494   int* sampleDimensions = self->GetSampleDimensions();
495 
496   // so we know how to scale if desired
497   double scaleFactor = 0;         // 0 used to indicate not scaling
498   double toDoubleScaleFactor = 0; // 0 used to indicate not scaling
499   double capValue = 0;            // 0 used to indicate not clamping (float or double)
500   if (self->GetOutputScalarType() != VTK_FLOAT && self->GetOutputScalarType() != VTK_DOUBLE)
501   {
502     capValue = self->GetCapValue();
503     if (self->GetScaleToMaximumDistance())
504     {
505       scaleFactor = capValue / maxDistance;
506       toDoubleScaleFactor = maxDistance / capValue;
507     }
508   }
509 
510   //
511   // Traverse all cells; computing distance function on volume points.
512   //
513   vtkCell* cell;
514   updateTime = input->GetNumberOfCells() / 50; // update every 2%
515   if (updateTime < 1)
516   {
517     updateTime = 1;
518   }
519 
520   for (cellNum = 0; cellNum < input->GetNumberOfCells(); cellNum++)
521   {
522     cell = input->GetCell(cellNum);
523     const double* bounds = cell->GetBounds();
524     for (i = 0; i < 3; i++)
525     {
526       adjBounds[2 * i] = bounds[2 * i] - maxDistance;
527       adjBounds[2 * i + 1] = bounds[2 * i + 1] + maxDistance;
528     }
529 
530     // compute dimensional bounds in data set
531     for (i = 0; i < 3; i++)
532     {
533       outExt[i * 2] = (int)((double)(adjBounds[2 * i] - origin[i]) / spacing[i]);
534       outExt[i * 2 + 1] = (int)((double)(adjBounds[2 * i + 1] - origin[i]) / spacing[i]);
535       if (outExt[i * 2] < 0)
536       {
537         outExt[i * 2] = 0;
538       }
539       if (outExt[i * 2 + 1] >= sampleDimensions[i])
540       {
541         outExt[i * 2 + 1] = sampleDimensions[i] - 1;
542       }
543     }
544 
545     vtkImageIterator<OT> outIt(outData, outExt);
546 
547     for (k = outExt[4]; k <= outExt[5]; k++)
548     {
549       x[2] = spacing[2] * k + origin[2];
550       for (j = outExt[2]; j <= outExt[3]; j++)
551       {
552         x[1] = spacing[1] * j + origin[1];
553         OT* outSI = outIt.BeginSpan();
554         for (i = outExt[0]; i <= outExt[1]; i++)
555         {
556           x[0] = spacing[0] * i + origin[0];
557 
558           ConvertToDoubleDistance(*outSI, distance, prevDistance2, toDoubleScaleFactor);
559 
560           // union combination of distances
561           if (cell->EvaluatePosition(x, closestPoint, subId, pcoords, distance2, weights) != -1 &&
562             distance2 < prevDistance2 && distance2 <= maxDistance2)
563           {
564             distance = sqrt(distance2);
565             SetOutputDistance(distance, outSI, capValue, scaleFactor);
566           }
567           outSI++;
568         }
569         outIt.NextSpan();
570       }
571     }
572 
573     if (cellNum % updateTime == 0)
574     {
575       self->UpdateProgress(double(cellNum + 1) / input->GetNumberOfCells());
576     }
577   }
578   delete[] weights;
579 }
580 
581 // Append a data set to the existing output. To use this function,
582 // you'll have to invoke the StartAppend() method before doing
583 // successive appends. It's also a good idea to specify the model
584 // bounds; otherwise the input model bounds is used. When you've
585 // finished appending, use the EndAppend() method.
Append(vtkDataSet * input)586 void vtkImplicitModeller::Append(vtkDataSet* input)
587 {
588   vtkDebugMacro(<< "Appending data");
589 
590   vtkImageData* output = this->GetOutput();
591 
592   if (!this->BoundsComputed)
593   {
594     this->ComputeModelBounds(input);
595   }
596 
597   if (this->ProcessMode == VTK_CELL_MODE)
598   {
599     if (!output->GetPointData()->GetScalars())
600     {
601       vtkErrorMacro("Sanity check failed.");
602       return;
603     }
604 
605     switch (this->OutputScalarType)
606     {
607       vtkTemplateMacro(vtkImplicitModellerAppendExecute(
608         this, input, output, this->InternalMaxDistance, static_cast<VTK_TT*>(nullptr)));
609     }
610   }
611   else
612   {
613     vtkImplicitModellerAppendInfo info;
614     double minZ, maxZ;
615     int slabMin, slabMax, slabSize, i;
616     vtkClipPolyData **minClipper = nullptr, **maxClipper = nullptr;
617     vtkPlane **minPlane = nullptr, **maxPlane = nullptr;
618     double *spacing, *origin;
619 
620     spacing = output->GetSpacing();
621     origin = output->GetOrigin();
622 
623     // Use a MultiThreader here, splitting the volume into slabs to be processed
624     // by the separate threads
625 
626     // Set the number of threads to use,
627     // then set the execution method and do it.
628     this->Threader->SetNumberOfThreads(this->NumberOfThreads);
629 
630     // set up the info object for the thread
631     info.Modeller = this;
632     info.MaximumDistance = this->InternalMaxDistance;
633 
634     info.Input = new vtkDataSet*[this->NumberOfThreads];
635     if (this->NumberOfThreads == 1)
636     {
637       info.Input[0] = input;
638     }
639     else
640     {
641       // if not PolyData, then copy the input for each thread
642       if (input->GetDataObjectType() != VTK_POLY_DATA)
643       {
644         for (i = 0; i < this->NumberOfThreads; i++)
645         {
646           switch (input->GetDataObjectType())
647           {
648             case VTK_STRUCTURED_GRID:
649               info.Input[i] = vtkStructuredGrid::New();
650               break;
651             case VTK_IMAGE_DATA:
652               info.Input[i] = vtkImageData::New();
653               break;
654             case VTK_UNSTRUCTURED_GRID:
655               info.Input[i] = vtkUnstructuredGrid::New();
656               break;
657             case VTK_RECTILINEAR_GRID:
658               info.Input[i] = vtkRectilinearGrid::New();
659               break;
660             default:
661               vtkErrorMacro(<< "Unexpected DataSet type!");
662               delete[] info.Input;
663               return;
664           }
665           info.Input[i]->CopyStructure(input);
666         }
667       }
668       else // break up the input data into slabs to help ensure thread safety
669 
670       {
671         minClipper = new vtkClipPolyData*[this->NumberOfThreads];
672         maxClipper = new vtkClipPolyData*[this->NumberOfThreads];
673         minPlane = new vtkPlane*[this->NumberOfThreads];
674         maxPlane = new vtkPlane*[this->NumberOfThreads];
675 
676         slabSize = this->SampleDimensions[2] / this->NumberOfThreads;
677         if (slabSize == 0) // in case threadCount >  SampleDimensions[2]
678         {
679           slabSize = 1;
680         }
681 
682         for (i = 0; i < this->NumberOfThreads; i++)
683         {
684           minPlane[i] = maxPlane[i] = nullptr;
685           //////////////////////////////////////////////////
686           // do the 1st clip
687           slabMin = i * slabSize;
688           if (slabMin >= this->SampleDimensions[2])
689           {
690             break;
691           }
692 
693           // get/clip input cells in this slab + maxDistance+
694           minZ = spacing[2] * slabMin + origin[2] - this->InternalMaxDistance * 1.00001;
695           if (minZ < this->ModelBounds[4])
696           {
697             minZ = this->ModelBounds[4];
698           }
699 
700           minPlane[i] = vtkPlane::New();
701           minPlane[i]->SetNormal(0.0, 0.0, -1.0);
702           minPlane[i]->SetOrigin(0.0, 0.0, minZ);
703 
704           minClipper[i] = vtkClipPolyData::New();
705           minClipper[i]->SetInputData((vtkPolyData*)input);
706           minClipper[i]->SetClipFunction(minPlane[i]);
707           minClipper[i]->SetValue(0.0);
708           minClipper[i]->InsideOutOn();
709           minClipper[i]->Update();
710 
711           if (minClipper[i]->GetOutput()->GetNumberOfCells() == 0)
712           {
713             info.Input[i] = nullptr;
714             maxPlane[i] = nullptr;
715             continue;
716           }
717           minClipper[i]->ReleaseDataFlagOn();
718 
719           //////////////////////////////////////////////////
720           // do the 2nd clip
721           slabMax = slabMin + slabSize - 1;
722           if (i == this->NumberOfThreads - 1)
723           {
724             slabMax = this->SampleDimensions[2] - 1;
725           }
726 
727           maxZ = spacing[2] * slabMax + origin[2] + this->InternalMaxDistance * 1.00001;
728           if (maxZ > this->ModelBounds[5])
729           {
730             maxZ = this->ModelBounds[5];
731           }
732           maxPlane[i] = vtkPlane::New();
733           maxPlane[i]->SetNormal(0.0, 0.0, 1.0);
734           maxPlane[i]->SetOrigin(0.0, 0.0, maxZ);
735 
736           maxClipper[i] = vtkClipPolyData::New();
737           maxClipper[i]->SetInputConnection(minClipper[i]->GetOutputPort());
738           maxClipper[i]->SetClipFunction(maxPlane[i]);
739           maxClipper[i]->SetValue(0.0);
740           maxClipper[i]->InsideOutOn();
741           maxClipper[i]->Update();
742 
743           if (maxClipper[i]->GetOutput()->GetNumberOfCells() == 0)
744           {
745             info.Input[i] = nullptr;
746           }
747           else
748           {
749             info.Input[i] = maxClipper[i]->GetOutput();
750           }
751         }
752         for (i++; i < this->NumberOfThreads; i++)
753         {
754           minPlane[i] = maxPlane[i] = nullptr;
755         }
756       }
757     }
758 
759     this->Threader->SetSingleMethod(vtkImplicitModeller_ThreadedAppend, (void*)&info);
760     this->Threader->SingleMethodExecute();
761 
762     // cleanup
763     if (this->NumberOfThreads > 1)
764     {
765       if (input->GetDataObjectType() != VTK_POLY_DATA)
766       {
767         for (i = 0; i < this->NumberOfThreads; i++)
768         {
769           info.Input[i]->Delete();
770         }
771       }
772       else
773       {
774         for (i = 0; i < this->NumberOfThreads; i++)
775         {
776           if (minPlane[i])
777           {
778             minPlane[i]->Delete();
779             minClipper[i]->Delete();
780           }
781           if (maxPlane[i])
782           {
783             maxPlane[i]->Delete();
784             maxClipper[i]->Delete();
785           }
786         }
787         delete[] minPlane;
788         delete[] maxPlane;
789         delete[] minClipper;
790         delete[] maxClipper;
791       }
792     }
793     delete[] info.Input;
794   }
795 }
796 
797 //------------------------------------------------------------------------------
798 // Method completes the append process (does the capping if requested).
EndAppend()799 void vtkImplicitModeller::EndAppend()
800 {
801   vtkDataArray* newScalars;
802   vtkDebugMacro(<< "End append");
803 
804   if (!(newScalars = this->GetOutput()->GetPointData()->GetScalars()))
805   {
806     vtkErrorMacro("Sanity check failed.");
807     return;
808   }
809 
810   if (this->Capping)
811   {
812     this->Cap(newScalars);
813   }
814   this->UpdateProgress(1.0);
815 }
816 
817 //------------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)818 int vtkImplicitModeller::RequestInformation(vtkInformation* vtkNotUsed(request),
819   vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector)
820 {
821   // get the info objects
822   vtkInformation* outInfo = outputVector->GetInformationObject(0);
823 
824   int i;
825   double ar[3], origin[3];
826 
827   vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->OutputScalarType, 1);
828 
829   outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), 0, this->SampleDimensions[0] - 1,
830     0, this->SampleDimensions[1] - 1, 0, this->SampleDimensions[2] - 1);
831 
832   for (i = 0; i < 3; i++)
833   {
834     origin[i] = this->ModelBounds[2 * i];
835     if (this->SampleDimensions[i] <= 1)
836     {
837       ar[i] = 1;
838     }
839     else
840     {
841       ar[i] =
842         (this->ModelBounds[2 * i + 1] - this->ModelBounds[2 * i]) / (this->SampleDimensions[i] - 1);
843     }
844   }
845   outInfo->Set(vtkDataObject::ORIGIN(), origin, 3);
846   outInfo->Set(vtkDataObject::SPACING(), ar, 3);
847 
848   return 1;
849 }
850 
851 //------------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * vtkNotUsed (outputVector))852 int vtkImplicitModeller::RequestData(vtkInformation* vtkNotUsed(request),
853   vtkInformationVector** inputVector, vtkInformationVector* vtkNotUsed(outputVector))
854 {
855   // get the input
856   vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
857   vtkDataSet* input = vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
858 
859   vtkDebugMacro(<< "Executing implicit model");
860 
861   if (input == nullptr)
862   {
863     // we do not want to release the data because user might
864     // have called Append ...
865     return 0;
866   }
867 
868   this->StartAppend(1);
869   this->Append(input);
870   this->EndAppend();
871 
872   return 1;
873 }
874 
875 // Compute ModelBounds from input geometry.
ComputeModelBounds(vtkDataSet * input)876 double vtkImplicitModeller::ComputeModelBounds(vtkDataSet* input)
877 {
878   const double* bounds;
879   double maxDist;
880   int i;
881   vtkImageData* output = this->GetOutput();
882   double tempd[3];
883 
884   // compute model bounds if not set previously
885   if (this->ModelBounds[0] >= this->ModelBounds[1] ||
886     this->ModelBounds[2] >= this->ModelBounds[3] || this->ModelBounds[4] >= this->ModelBounds[5])
887   {
888     if (input != nullptr)
889     {
890       bounds = input->GetBounds();
891     }
892     else
893     {
894       vtkDataSet* dsInput = vtkDataSet::SafeDownCast(this->GetInput());
895       if (dsInput != nullptr)
896       {
897         bounds = dsInput->GetBounds();
898       }
899       else
900       {
901         vtkErrorMacro(<< "An input must be specified to Compute the model bounds.");
902         return VTK_FLOAT_MAX;
903       }
904     }
905   }
906   else
907   {
908     bounds = this->ModelBounds;
909   }
910 
911   for (maxDist = 0.0, i = 0; i < 3; i++)
912   {
913     if ((bounds[2 * i + 1] - bounds[2 * i]) > maxDist)
914     {
915       maxDist = bounds[2 * i + 1] - bounds[2 * i];
916     }
917   }
918 
919   // adjust bounds so model fits strictly inside (only if not set previously)
920   if (this->AdjustBounds)
921   {
922     for (i = 0; i < 3; i++)
923     {
924       this->ModelBounds[2 * i] = bounds[2 * i] - maxDist * this->AdjustDistance;
925       this->ModelBounds[2 * i + 1] = bounds[2 * i + 1] + maxDist * this->AdjustDistance;
926     }
927   }
928   else // to handle problem case where bounds not specified and AdjustBounds
929        //  not on; will be setting ModelBounds to self if previosusly set
930   {
931     for (i = 0; i < 3; i++)
932     {
933       this->ModelBounds[2 * i] = bounds[2 * i];
934       this->ModelBounds[2 * i + 1] = bounds[2 * i + 1];
935     }
936   }
937 
938   maxDist *= this->MaximumDistance;
939 
940   // Set volume origin and data spacing
941   output->SetOrigin(this->ModelBounds[0], this->ModelBounds[2], this->ModelBounds[4]);
942 
943   for (i = 0; i < 3; i++)
944   {
945     tempd[i] =
946       (this->ModelBounds[2 * i + 1] - this->ModelBounds[2 * i]) / (this->SampleDimensions[i] - 1);
947   }
948   output->SetSpacing(tempd);
949 
950   vtkInformation* outInfo = this->GetExecutive()->GetOutputInformation(0);
951   outInfo->Set(
952     vtkDataObject::ORIGIN(), this->ModelBounds[0], this->ModelBounds[2], this->ModelBounds[4]);
953   outInfo->Set(vtkDataObject::SPACING(), tempd, 3);
954 
955   this->BoundsComputed = 1;
956   this->InternalMaxDistance = maxDist;
957 
958   return maxDist;
959 }
960 
961 //------------------------------------------------------------------------------
962 // Set the i-j-k dimensions on which to sample the distance function.
SetSampleDimensions(int i,int j,int k)963 void vtkImplicitModeller::SetSampleDimensions(int i, int j, int k)
964 {
965   int dim[3];
966 
967   dim[0] = i;
968   dim[1] = j;
969   dim[2] = k;
970 
971   this->SetSampleDimensions(dim);
972 }
973 
974 //------------------------------------------------------------------------------
SetSampleDimensions(int dim[3])975 void vtkImplicitModeller::SetSampleDimensions(int dim[3])
976 {
977   int dataDim, i;
978 
979   vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2]
980                 << ")");
981 
982   if (dim[0] != this->SampleDimensions[0] || dim[1] != this->SampleDimensions[1] ||
983     dim[2] != this->SampleDimensions[2])
984   {
985     if (dim[0] < 1 || dim[1] < 1 || dim[2] < 1)
986     {
987       vtkErrorMacro(<< "Bad Sample Dimensions, retaining previous values");
988       return;
989     }
990 
991     for (dataDim = 0, i = 0; i < 3; i++)
992     {
993       if (dim[i] > 1)
994       {
995         dataDim++;
996       }
997     }
998 
999     if (dataDim < 3)
1000     {
1001       vtkErrorMacro(<< "Sample dimensions must define a volume!");
1002       return;
1003     }
1004 
1005     for (i = 0; i < 3; i++)
1006     {
1007       this->SampleDimensions[i] = dim[i];
1008     }
1009 
1010     this->Modified();
1011   }
1012 }
1013 
1014 //------------------------------------------------------------------------------
Cap(vtkDataArray * s)1015 void vtkImplicitModeller::Cap(vtkDataArray* s)
1016 {
1017   int i, j, k;
1018   int idx;
1019   int d01 = this->SampleDimensions[0] * this->SampleDimensions[1];
1020 
1021   // i-j planes
1022   for (j = 0; j < this->SampleDimensions[1]; j++)
1023   {
1024     for (i = 0; i < this->SampleDimensions[0]; i++)
1025     {
1026       s->SetComponent(i + j * this->SampleDimensions[0], 0, this->CapValue);
1027     }
1028   }
1029   k = this->SampleDimensions[2] - 1;
1030   idx = k * d01;
1031   for (j = 0; j < this->SampleDimensions[1]; j++)
1032   {
1033     for (i = 0; i < this->SampleDimensions[0]; i++)
1034     {
1035       s->SetComponent(idx + i + j * this->SampleDimensions[0], 0, this->CapValue);
1036     }
1037   }
1038   // j-k planes
1039   for (k = 0; k < this->SampleDimensions[2]; k++)
1040   {
1041     for (j = 0; j < this->SampleDimensions[1]; j++)
1042     {
1043       s->SetComponent(j * this->SampleDimensions[0] + k * d01, 0, this->CapValue);
1044     }
1045   }
1046   i = this->SampleDimensions[0] - 1;
1047   for (k = 0; k < this->SampleDimensions[2]; k++)
1048   {
1049     for (j = 0; j < this->SampleDimensions[1]; j++)
1050     {
1051       s->SetComponent(i + j * this->SampleDimensions[0] + k * d01, 0, this->CapValue);
1052     }
1053   }
1054   // i-k planes
1055   for (k = 0; k < this->SampleDimensions[2]; k++)
1056   {
1057     for (i = 0; i < this->SampleDimensions[0]; i++)
1058     {
1059       s->SetComponent(i + k * d01, 0, this->CapValue);
1060     }
1061   }
1062   j = this->SampleDimensions[1] - 1;
1063   idx = j * this->SampleDimensions[0];
1064   for (k = 0; k < this->SampleDimensions[2]; k++)
1065   {
1066     for (i = 0; i < this->SampleDimensions[0]; i++)
1067     {
1068       s->SetComponent(idx + i + k * d01, 0, this->CapValue);
1069     }
1070   }
1071 }
1072 
1073 //------------------------------------------------------------------------------
GetProcessModeAsString()1074 const char* vtkImplicitModeller::GetProcessModeAsString()
1075 {
1076   if (this->ProcessMode == VTK_CELL_MODE)
1077   {
1078     return "PerCell";
1079   }
1080   else
1081   {
1082     return "PerVoxel";
1083   }
1084 }
1085 
1086 //------------------------------------------------------------------------------
FillInputPortInformation(int vtkNotUsed (port),vtkInformation * info)1087 int vtkImplicitModeller::FillInputPortInformation(int vtkNotUsed(port), vtkInformation* info)
1088 {
1089   info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
1090   info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
1091   return 1;
1092 }
1093 
1094 //------------------------------------------------------------------------------
ProcessRequest(vtkInformation * request,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)1095 vtkTypeBool vtkImplicitModeller::ProcessRequest(
1096   vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
1097 {
1098   // If we have no input then we will not generate the output because
1099   // the user already called StartAppend/Append/EndAppend.
1100   if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_NOT_GENERATED()))
1101   {
1102     if (inputVector[0]->GetNumberOfInformationObjects() == 0)
1103     {
1104       vtkInformation* outInfo = outputVector->GetInformationObject(0);
1105       outInfo->Set(vtkDemandDrivenPipeline::DATA_NOT_GENERATED(), 1);
1106     }
1107     return 1;
1108   }
1109   else if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
1110   {
1111     if (inputVector[0]->GetNumberOfInformationObjects() == 0)
1112     {
1113       return 1;
1114     }
1115   }
1116   return this->Superclass::ProcessRequest(request, inputVector, outputVector);
1117 }
1118 
PrintSelf(ostream & os,vtkIndent indent)1119 void vtkImplicitModeller::PrintSelf(ostream& os, vtkIndent indent)
1120 {
1121   this->Superclass::PrintSelf(os, indent);
1122 
1123   os << indent << "Maximum Distance: " << this->MaximumDistance << "\n";
1124   os << indent << "OutputScalarType: " << this->OutputScalarType << "\n";
1125   os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", "
1126      << this->SampleDimensions[1] << ", " << this->SampleDimensions[2] << ")\n";
1127   os << indent << "ModelBounds: \n";
1128   os << indent << "  Xmin,Xmax: (" << this->ModelBounds[0] << ", " << this->ModelBounds[1] << ")\n";
1129   os << indent << "  Ymin,Ymax: (" << this->ModelBounds[2] << ", " << this->ModelBounds[3] << ")\n";
1130   os << indent << "  Zmin,Zmax: (" << this->ModelBounds[4] << ", " << this->ModelBounds[5] << ")\n";
1131 
1132   os << indent << "ScaleToMaximumDistance: " << (this->ScaleToMaximumDistance ? "On\n" : "Off\n");
1133   os << indent << "AdjustBounds: " << (this->AdjustBounds ? "On\n" : "Off\n");
1134   os << indent << "Adjust Distance: " << this->AdjustDistance << "\n";
1135   os << indent << "Process Mode: " << this->ProcessMode << "\n";
1136   os << indent << "Locator Max Level: " << this->LocatorMaxLevel << "\n";
1137 
1138   os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
1139   os << indent << "Cap Value: " << this->CapValue << "\n";
1140   os << indent << "Process Mode: " << this->GetProcessModeAsString() << endl;
1141   os << indent << "Number Of Threads (for PerVoxel mode): " << this->NumberOfThreads << endl;
1142 }
1143