1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkExtractSelectedThresholds.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 "vtkExtractSelectedThresholds.h"
16 
17 #include "vtkCellData.h"
18 #include "vtkCell.h"
19 #include "vtkDataSet.h"
20 #include "vtkDoubleArray.h"
21 #include "vtkIdList.h"
22 #include "vtkIdTypeArray.h"
23 #include "vtkInformation.h"
24 #include "vtkInformationVector.h"
25 #include "vtkObjectFactory.h"
26 #include "vtkPointData.h"
27 #include "vtkSelection.h"
28 #include "vtkSelectionNode.h"
29 #include "vtkSignedCharArray.h"
30 #include "vtkSmartPointer.h"
31 #include "vtkTable.h"
32 #include "vtkThreshold.h"
33 #include "vtkUnstructuredGrid.h"
34 
35 #include <algorithm>
36 
37 vtkStandardNewMacro(vtkExtractSelectedThresholds);
38 
39 //----------------------------------------------------------------------------
vtkExtractSelectedThresholds()40 vtkExtractSelectedThresholds::vtkExtractSelectedThresholds()
41 {
42   this->SetNumberOfInputPorts(2);
43 }
44 
45 //----------------------------------------------------------------------------
~vtkExtractSelectedThresholds()46 vtkExtractSelectedThresholds::~vtkExtractSelectedThresholds()
47 {
48 }
49 
50 //----------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)51 int vtkExtractSelectedThresholds::RequestData(
52   vtkInformation *vtkNotUsed(request),
53   vtkInformationVector **inputVector,
54   vtkInformationVector *outputVector)
55 {
56   // get the info objects
57   vtkInformation *selInfo = inputVector[1]->GetInformationObject(0);
58   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
59   vtkInformation *outInfo = outputVector->GetInformationObject(0);
60 
61 
62   vtkDataObject* inputDO = vtkDataObject::GetData(inInfo);
63 
64   // verify the input, selection and ouptut
65   if ( ! selInfo )
66     {
67     //When not given a selection, quietly select nothing.
68     return 1;
69     }
70 
71   vtkSelection *sel = vtkSelection::GetData(selInfo);
72   vtkSelectionNode *node = 0;
73   if (sel->GetNumberOfNodes() == 1)
74     {
75     node = sel->GetNode(0);
76     }
77   if (!node)
78     {
79     vtkErrorMacro("Selection must have a single node.");
80     return 1;
81     }
82   if (!node->GetProperties()->Has(vtkSelectionNode::CONTENT_TYPE()) ||
83       node->GetProperties()->Get(vtkSelectionNode::CONTENT_TYPE()) != vtkSelectionNode::THRESHOLDS)
84     {
85     vtkErrorMacro("Missing or invalid CONTENT_TYPE.");
86     return 1;
87     }
88 
89   if (vtkDataSet* input = vtkDataSet::SafeDownCast(inputDO))
90     {
91     if (input->GetNumberOfCells() == 0 && input->GetNumberOfPoints() == 0)
92       {
93       // empty input, nothing to do..
94       return 1;
95       }
96 
97     vtkDataSet *output = vtkDataSet::GetData(outInfo);
98     vtkDebugMacro(<< "Extracting from dataset");
99 
100     int thresholdByPointVals = 0;
101     int fieldType = vtkSelectionNode::CELL;
102     if (node->GetProperties()->Has(vtkSelectionNode::FIELD_TYPE()))
103       {
104       fieldType = node->GetProperties()->Get(vtkSelectionNode::FIELD_TYPE());
105       if (fieldType == vtkSelectionNode::POINT)
106         {
107         if (node->GetProperties()->Has(vtkSelectionNode::CONTAINING_CELLS()))
108           {
109           thresholdByPointVals =
110             node->GetProperties()->Get(vtkSelectionNode::CONTAINING_CELLS());
111           }
112         }
113       }
114 
115     if (thresholdByPointVals || fieldType == vtkSelectionNode::CELL)
116       {
117       return this->ExtractCells(node, input, output, thresholdByPointVals);
118       }
119     if (fieldType == vtkSelectionNode::POINT)
120       {
121       return this->ExtractPoints(node, input, output);
122       }
123     }
124   else if (vtkTable* inputTable = vtkTable::SafeDownCast(inputDO))
125     {
126     if (inputTable->GetNumberOfRows() == 0)
127       {
128       return 1;
129       }
130     vtkTable* output = vtkTable::GetData(outInfo);
131     return this->ExtractRows(node, inputTable, output);
132     }
133 
134   return 0;
135 }
136 
137 //----------------------------------------------------------------------------
ExtractCells(vtkSelectionNode * sel,vtkDataSet * input,vtkDataSet * output,int usePointScalars)138 int vtkExtractSelectedThresholds::ExtractCells(
139   vtkSelectionNode *sel,
140   vtkDataSet *input,
141   vtkDataSet *output,
142   int usePointScalars)
143 {
144   //find the values to threshold within
145   vtkDataArray *lims = vtkDataArray::SafeDownCast(sel->GetSelectionList());
146   if (lims == NULL)
147     {
148     vtkErrorMacro(<<"No values to threshold with");
149     return 1;
150     }
151 
152   //find out what array we are supposed to threshold in
153   vtkDataArray *inScalars = NULL;
154   bool use_ids = false;
155   if (usePointScalars)
156     {
157     if (sel->GetSelectionList()->GetName())
158       {
159       if (strcmp(sel->GetSelectionList()->GetName(), "vtkGlobalIds") == 0)
160         {
161         inScalars = input->GetPointData()->GetGlobalIds();
162         }
163       else if (strcmp(sel->GetSelectionList()->GetName(), "vtkIndices") == 0)
164         {
165         use_ids = true;
166         }
167       else
168         {
169         inScalars = input->GetPointData()->GetArray(
170           sel->GetSelectionList()->GetName());
171         }
172       }
173     else
174       {
175       inScalars = input->GetPointData()->GetScalars();
176       }
177     }
178   else
179     {
180     if (sel->GetSelectionList()->GetName())
181       {
182       if (strcmp(sel->GetSelectionList()->GetName(), "vtkGlobalIds") == 0)
183         {
184         inScalars = input->GetCellData()->GetGlobalIds();
185         }
186       else if (strcmp(sel->GetSelectionList()->GetName(), "vtkIndices") == 0)
187         {
188         use_ids = true;
189         }
190       else
191         {
192         inScalars = input->GetCellData()->GetArray(
193           sel->GetSelectionList()->GetName());
194         }
195       }
196     else
197       {
198       inScalars = input->GetCellData()->GetScalars();
199       }
200     }
201   if (inScalars == NULL && !use_ids)
202     {
203     vtkErrorMacro("Could not figure out what array to threshold in.");
204     return 1;
205     }
206 
207   int inverse = 0;
208   if (sel->GetProperties()->Has(vtkSelectionNode::INVERSE()))
209     {
210     inverse = sel->GetProperties()->Get(vtkSelectionNode::INVERSE());
211     }
212 
213   int passThrough = 0;
214   if (this->PreserveTopology)
215     {
216     passThrough = 1;
217     }
218 
219   int comp_no = 0;
220   if (sel->GetProperties()->Has(vtkSelectionNode::COMPONENT_NUMBER()))
221     {
222     comp_no = sel->GetProperties()->Get(vtkSelectionNode::COMPONENT_NUMBER());
223     }
224 
225   vtkIdType cellId, newCellId;
226   vtkIdList *cellPts, *pointMap = NULL;
227   vtkIdList *newCellPts = NULL;
228   vtkCell *cell = 0;
229   vtkPoints *newPoints = 0;
230   vtkIdType i, ptId, newId, numPts, numCells;
231   int numCellPts;
232   double x[3];
233 
234   vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData();
235   vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData();
236   int keepCell;
237 
238 
239   outPD->CopyGlobalIdsOn();
240   outPD->CopyAllocate(pd);
241   outCD->CopyGlobalIdsOn();
242   outCD->CopyAllocate(cd);
243 
244   numPts = input->GetNumberOfPoints();
245   numCells = input->GetNumberOfCells();
246 
247   vtkDataSet *outputDS = output;
248   vtkSignedCharArray *pointInArray = NULL;
249   vtkSignedCharArray *cellInArray = NULL;
250 
251   vtkUnstructuredGrid *outputUG = NULL;
252   vtkIdTypeArray *originalCellIds = NULL;
253   vtkIdTypeArray *originalPointIds = NULL;
254 
255   signed char flag = inverse ? 1 : -1;
256 
257   if (passThrough)
258     {
259     outputDS->ShallowCopy(input);
260 
261     pointInArray = vtkSignedCharArray::New();
262     pointInArray->SetNumberOfComponents(1);
263     pointInArray->SetNumberOfTuples(numPts);
264     for (i=0; i < numPts; i++)
265       {
266       pointInArray->SetValue(i, flag);
267       }
268     pointInArray->SetName("vtkInsidedness");
269     outPD->AddArray(pointInArray);
270     outPD->SetScalars(pointInArray);
271 
272     cellInArray = vtkSignedCharArray::New();
273     cellInArray->SetNumberOfComponents(1);
274     cellInArray->SetNumberOfTuples(numCells);
275     for (i=0; i < numCells; i++)
276       {
277       cellInArray->SetValue(i, flag);
278       }
279     cellInArray->SetName("vtkInsidedness");
280     outCD->AddArray(cellInArray);
281     outCD->SetScalars(cellInArray);
282     }
283   else
284     {
285     outputUG = vtkUnstructuredGrid::SafeDownCast(output);
286     outputUG->Allocate(input->GetNumberOfCells());
287     newPoints = vtkPoints::New();
288     newPoints->Allocate(numPts);
289 
290     pointMap = vtkIdList::New(); //maps old point ids into new
291     pointMap->SetNumberOfIds(numPts);
292     for (i=0; i < numPts; i++)
293       {
294       pointMap->SetId(i,-1);
295       }
296 
297     newCellPts = vtkIdList::New();
298 
299     originalCellIds = vtkIdTypeArray::New();
300     originalCellIds->SetName("vtkOriginalCellIds");
301     originalCellIds->SetNumberOfComponents(1);
302     outCD->AddArray(originalCellIds);
303 
304     originalPointIds = vtkIdTypeArray::New();
305     originalPointIds->SetName("vtkOriginalPointIds");
306     originalPointIds->SetNumberOfComponents(1);
307     outPD->AddArray(originalPointIds);
308     originalPointIds->Delete();
309     }
310 
311   flag = -flag;
312 
313   // Check that the scalars of each cell satisfy the threshold criterion
314   for (cellId=0; cellId < input->GetNumberOfCells(); cellId++)
315     {
316     cell = input->GetCell(cellId);
317     cellPts = cell->GetPointIds();
318     numCellPts = cell->GetNumberOfPoints();
319 
320     // BUG: This code misses the case where the threshold is contained
321     // completely within the cell but none of its points are inside
322     // the range.  Consider as an example the threshold range [1, 2]
323     // with a cell [0, 3].
324     if ( usePointScalars )
325       {
326       keepCell = 0;
327       int totalAbove = 0;
328       int totalBelow = 0;
329       for ( i=0;
330             (i < numCellPts) && (passThrough || !keepCell);
331             i++)
332         {
333         int above = 0;
334         int below = 0;
335         ptId = cellPts->GetId(i);
336         int inside = this->EvaluateValue(
337           inScalars, comp_no, ptId, lims, &above, &below, NULL);
338         totalAbove += above;
339         totalBelow += below;
340         // Have we detected a cell that straddles the threshold?
341         if ((!inside) && (totalAbove && totalBelow))
342           {
343           inside = 1;
344           }
345         if (passThrough && (inside ^ inverse))
346           {
347           pointInArray->SetValue(ptId, flag);
348           cellInArray->SetValue(cellId, flag);
349           }
350         keepCell |= inside;
351         }
352       }
353     else //use cell scalars
354       {
355       keepCell = this->EvaluateValue(inScalars, comp_no, cellId, lims);
356       if (passThrough && (keepCell ^ inverse))
357         {
358         cellInArray->SetValue(cellId, flag);
359         }
360       }
361 
362     if (  !passThrough &&
363           (numCellPts > 0) &&
364           (keepCell + inverse == 1) ) // Poor man's XOR
365       {
366       // satisfied thresholding (also non-empty cell, i.e. not VTK_EMPTY_CELL)
367       originalCellIds->InsertNextValue(cellId);
368 
369       for (i=0; i < numCellPts; i++)
370         {
371         ptId = cellPts->GetId(i);
372         if ( (newId = pointMap->GetId(ptId)) < 0 )
373           {
374           input->GetPoint(ptId, x);
375           newId = newPoints->InsertNextPoint(x);
376           pointMap->SetId(ptId,newId);
377           outPD->CopyData(pd,ptId,newId);
378           originalPointIds->InsertNextValue(ptId);
379           }
380         newCellPts->InsertId(i,newId);
381         }
382       newCellId = outputUG->InsertNextCell(cell->GetCellType(),newCellPts);
383       outCD->CopyData(cd,cellId,newCellId);
384       newCellPts->Reset();
385       } // satisfied thresholding
386     } // for all cells
387 
388   // now clean up / update ourselves
389   if (passThrough)
390     {
391     pointInArray->Delete();
392     cellInArray->Delete();
393     }
394   else
395     {
396     outputUG->SetPoints(newPoints);
397     newPoints->Delete();
398     pointMap->Delete();
399     newCellPts->Delete();
400     originalCellIds->Delete();
401     }
402 
403   output->Squeeze();
404 
405   return 1;
406 }
407 
408 //----------------------------------------------------------------------------
ExtractPoints(vtkSelectionNode * sel,vtkDataSet * input,vtkDataSet * output)409 int vtkExtractSelectedThresholds::ExtractPoints(
410   vtkSelectionNode *sel,
411   vtkDataSet *input,
412   vtkDataSet *output)
413 {
414   //find the values to threshold within
415   vtkDataArray *lims = vtkDataArray::SafeDownCast(sel->GetSelectionList());
416   if (lims == NULL)
417     {
418     vtkErrorMacro(<<"No values to threshold with");
419     return 1;
420     }
421 
422   //find out what array we are supposed to threshold in
423   vtkDataArray *inScalars = NULL;
424   bool use_ids = false;
425   if (sel->GetSelectionList()->GetName())
426     {
427     if (strcmp(sel->GetSelectionList()->GetName(), "vtkGlobalIds") == 0)
428       {
429       inScalars = input->GetPointData()->GetGlobalIds();
430       }
431     else if (strcmp(sel->GetSelectionList()->GetName(), "vtkIndices") == 0)
432       {
433       use_ids = true;
434       }
435     else
436       {
437       inScalars = input->GetPointData()->GetArray(
438         sel->GetSelectionList()->GetName());
439       }
440     }
441   else
442     {
443     inScalars = input->GetPointData()->GetScalars();
444     }
445   if (inScalars == NULL && !use_ids)
446     {
447     vtkErrorMacro("Could not figure out what array to threshold in.");
448     return 1;
449     }
450 
451   int inverse = 0;
452   if (sel->GetProperties()->Has(vtkSelectionNode::INVERSE()))
453     {
454     inverse = sel->GetProperties()->Get(vtkSelectionNode::INVERSE());
455     }
456 
457   int passThrough = 0;
458   if (this->PreserveTopology)
459     {
460     passThrough = 1;
461     }
462 
463   int comp_no = 0;
464   if (sel->GetProperties()->Has(vtkSelectionNode::COMPONENT_NUMBER()))
465     {
466     comp_no = sel->GetProperties()->Get(vtkSelectionNode::COMPONENT_NUMBER());
467     }
468 
469   vtkIdType numPts = input->GetNumberOfPoints();
470   vtkPointData *inputPD = input->GetPointData();
471   vtkPointData *outPD = output->GetPointData();
472 
473   vtkDataSet *outputDS = output;
474   vtkSignedCharArray *pointInArray = NULL;
475 
476   vtkUnstructuredGrid * outputUG = NULL;
477   vtkPoints *newPts = vtkPoints::New();
478 
479   vtkIdTypeArray* originalPointIds = 0;
480 
481   signed char flag = inverse ? 1 : -1;
482 
483   if (passThrough)
484     {
485     outputDS->ShallowCopy(input);
486 
487     pointInArray = vtkSignedCharArray::New();
488     pointInArray->SetNumberOfComponents(1);
489     pointInArray->SetNumberOfTuples(numPts);
490     for (vtkIdType i=0; i < numPts; i++)
491       {
492       pointInArray->SetValue(i, flag);
493       }
494     pointInArray->SetName("vtkInsidedness");
495     outPD->AddArray(pointInArray);
496     outPD->SetScalars(pointInArray);
497     }
498   else
499     {
500     outputUG = vtkUnstructuredGrid::SafeDownCast(output);
501     outputUG->Allocate(numPts);
502 
503     newPts->Allocate(numPts);
504     outputUG->SetPoints(newPts);
505 
506     outPD->CopyGlobalIdsOn();
507     outPD->CopyAllocate(inputPD);
508 
509     originalPointIds = vtkIdTypeArray::New();
510     originalPointIds->SetNumberOfComponents(1);
511     originalPointIds->SetName("vtkOriginalPointIds");
512     outPD->AddArray(originalPointIds);
513     originalPointIds->Delete();
514     }
515 
516   flag = -flag;
517 
518   vtkIdType outPtCnt = 0;
519   for (vtkIdType ptId = 0; ptId < numPts; ptId++)
520     {
521     int keepPoint = this->EvaluateValue( inScalars, comp_no, ptId, lims );
522     if (keepPoint ^ inverse)
523       {
524       if (passThrough)
525         {
526         pointInArray->SetValue(ptId, flag);
527         }
528       else
529         {
530         double X[4];
531         input->GetPoint(ptId, X);
532         newPts->InsertNextPoint(X);
533         outPD->CopyData(inputPD, ptId, outPtCnt);
534         originalPointIds->InsertNextValue(ptId);
535         outputUG->InsertNextCell(VTK_VERTEX, 1, &outPtCnt);
536         outPtCnt++;
537         }
538       }
539     }
540 
541   if (passThrough)
542     {
543     pointInArray->Delete();
544     }
545   newPts->Delete();
546   output->Squeeze();
547   return 1;
548 }
549 
550 //----------------------------------------------------------------------------
ExtractRows(vtkSelectionNode * sel,vtkTable * input,vtkTable * output)551 int vtkExtractSelectedThresholds::ExtractRows(
552   vtkSelectionNode* sel, vtkTable* input, vtkTable* output)
553 {
554   //find the values to threshold within
555   vtkDataArray *lims = vtkDataArray::SafeDownCast(sel->GetSelectionList());
556   if (lims == NULL)
557     {
558     vtkErrorMacro(<<"No values to threshold with");
559     return 1;
560     }
561 
562   // Determine the array to threshold.
563   vtkDataArray *inScalars = NULL;
564   bool use_ids = false;
565   if (sel->GetSelectionList()->GetName())
566     {
567     if (strcmp(sel->GetSelectionList()->GetName(), "vtkGlobalIds") == 0)
568       {
569       inScalars = input->GetRowData()->GetGlobalIds();
570       }
571     else if (strcmp(sel->GetSelectionList()->GetName(), "vtkIndices") == 0)
572       {
573       use_ids = true;
574       }
575     else
576       {
577       inScalars = input->GetRowData()->GetArray(
578         sel->GetSelectionList()->GetName());
579       }
580     }
581 
582   if (inScalars == NULL && !use_ids)
583     {
584     vtkErrorMacro("Could not figure out what array to threshold in.");
585     return 1;
586     }
587 
588   int inverse = 0;
589   if (sel->GetProperties()->Has(vtkSelectionNode::INVERSE()))
590     {
591     inverse = sel->GetProperties()->Get(vtkSelectionNode::INVERSE());
592     }
593 
594   int passThrough = 0;
595   if (this->PreserveTopology)
596     {
597     passThrough = 1;
598     }
599 
600   int comp_no = 0;
601   if (sel->GetProperties()->Has(vtkSelectionNode::COMPONENT_NUMBER()))
602     {
603     comp_no = sel->GetProperties()->Get(vtkSelectionNode::COMPONENT_NUMBER());
604     }
605 
606   vtkDataSetAttributes* inRD = input->GetRowData();
607   vtkDataSetAttributes* outRD = output->GetRowData();
608   vtkSmartPointer<vtkSignedCharArray> rowInArray;
609   vtkSmartPointer<vtkIdTypeArray> originalRowIds;
610   vtkIdType numRows = input->GetNumberOfRows();
611 
612   signed char flag = inverse ? 1 : -1;
613 
614   if (passThrough)
615     {
616     output->ShallowCopy(input);
617 
618     rowInArray = vtkSmartPointer<vtkSignedCharArray>::New();
619     rowInArray->SetNumberOfComponents(1);
620     rowInArray->SetNumberOfTuples(numRows);
621     std::fill(rowInArray->GetPointer(0), rowInArray->GetPointer(0) + numRows, flag);
622     rowInArray->SetName("vtkInsidedness");
623     outRD->AddArray(rowInArray);
624     }
625   else
626     {
627     outRD->CopyGlobalIdsOn();
628     outRD->CopyAllocate(inRD);
629 
630     originalRowIds = vtkSmartPointer<vtkIdTypeArray>::New();
631     originalRowIds->SetNumberOfComponents(1);
632     originalRowIds->SetName("vtkOriginalRowIds");
633     originalRowIds->Allocate(numRows);
634     outRD->AddArray(originalRowIds);
635     }
636 
637   flag = -flag;
638 
639   vtkIdType outRCnt = 0;
640   for (vtkIdType rowId = 0; rowId < numRows; rowId++)
641     {
642     int keepRow = this->EvaluateValue(inScalars, comp_no, rowId, lims);
643     if (keepRow ^ inverse)
644       {
645       if (passThrough)
646         {
647         rowInArray->SetValue(rowId, flag);
648         }
649       else
650         {
651         outRD->CopyData(inRD, rowId, outRCnt);
652         originalRowIds->InsertNextValue(rowId);
653         outRCnt++;
654         }
655       }
656     }
657   outRD->Squeeze();
658   return 1;
659 }
660 
661 
662 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)663 void vtkExtractSelectedThresholds::PrintSelf(ostream& os, vtkIndent indent)
664 {
665   this->Superclass::PrintSelf(os,indent);
666 
667 }
668 
669 namespace
670 {
671   template <class daT>
TestItem(vtkIdType numLims,daT * limsPtr,double value)672   bool TestItem(vtkIdType numLims, daT* limsPtr, double value)
673     {
674     for (int i = 0; i < numLims; i+=2)
675       {
676       if (value >= limsPtr[i] && value <= limsPtr[i+1])
677         {
678         return true;
679         }
680       }
681     return false;
682     }
683 
684   template <class daT>
TestItem(vtkIdType numLims,daT * limsPtr,double value,int & above,int & below,int & inside)685   bool TestItem(vtkIdType numLims, daT* limsPtr, double value,
686     int &above, int &below, int& inside)
687     {
688     bool keepCell = false;
689     for (vtkIdType i = 0; i < numLims; i+=2)
690       {
691       daT low = limsPtr[i];
692       daT high = limsPtr[i+1];
693       if (value >= low && value <= high)
694         {
695         keepCell = true;
696         ++inside;
697         }
698       else if (value < low)
699         {
700         ++below;
701         }
702       else if (value > high)
703         {
704         ++above;
705         }
706       }
707     return keepCell;
708     }
709 };
710 //----------------------------------------------------------------------------
EvaluateValue(vtkDataArray * scalars,int comp_no,vtkIdType id,vtkDataArray * lims)711 int vtkExtractSelectedThresholds::EvaluateValue(
712   vtkDataArray *scalars, int comp_no, vtkIdType id, vtkDataArray *lims)
713 {
714   int keepCell = 0;
715   //check the value in the array against all of the thresholds in lims
716   //if it is inside any, return true
717   double value = 0.0;
718   if (comp_no < 0 && scalars)
719     {
720     // use magnitude.
721     int numComps = scalars->GetNumberOfComponents();
722     const double *tuple = scalars->GetTuple(id);
723     for (int cc=0; cc < numComps; cc++)
724       {
725       value += tuple[cc]*tuple[cc];
726       }
727     value = sqrt(value);
728     }
729   else
730     {
731     value = scalars? scalars->GetComponent(id, comp_no) :
732       static_cast<double>(id); /// <=== precision loss when using id.
733     }
734 
735   void* rawLimsPtr = lims->GetVoidPointer(0);
736   vtkIdType numLims = lims->GetNumberOfComponents() * lims->GetNumberOfTuples();
737   switch (lims->GetDataType())
738     {
739     vtkTemplateMacro(
740       keepCell = TestItem<VTK_TT>(numLims,
741         static_cast<VTK_TT*>(rawLimsPtr),
742         value));
743     }
744   return keepCell;
745 }
746 
747 
748 //----------------------------------------------------------------------------
EvaluateValue(vtkDataArray * scalars,int comp_no,vtkIdType id,vtkDataArray * lims,int * AboveCount,int * BelowCount,int * InsideCount)749 int vtkExtractSelectedThresholds::EvaluateValue(
750   vtkDataArray *scalars, int comp_no, vtkIdType id, vtkDataArray *lims,
751   int *AboveCount, int *BelowCount, int *InsideCount)
752 {
753   double value = 0.0;
754   if (comp_no < 0 && scalars)
755     {
756     // use magnitude.
757     int numComps = scalars->GetNumberOfComponents();
758     const double *tuple = scalars->GetTuple(id);
759     for (int cc=0; cc < numComps; cc++)
760       {
761       value += tuple[cc]*tuple[cc];
762       }
763     value = sqrt(value);
764     }
765   else
766     {
767     value = scalars? scalars->GetComponent(id, comp_no) :
768       static_cast<double>(id); /// <=== precision loss when using id.
769     }
770 
771   int keepCell = 0;
772   //check the value in the array against all of the thresholds in lims
773   //if it is inside any, return true
774   int above = 0;
775   int below = 0;
776   int inside = 0;
777 
778   void* rawLimsPtr = lims->GetVoidPointer(0);
779   vtkIdType numLims = lims->GetNumberOfComponents() * lims->GetNumberOfTuples();
780   switch (lims->GetDataType())
781     {
782     vtkTemplateMacro(
783       keepCell = TestItem<VTK_TT>(numLims,
784         static_cast<VTK_TT*>(rawLimsPtr),
785         value,
786         above, below, inside));
787     }
788 
789   if (AboveCount) *AboveCount = above;
790   if (BelowCount) *BelowCount = below;
791   if (InsideCount) *InsideCount = inside;
792   return keepCell;
793 }
794 
795