1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkConnectivityFilter.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 "vtkConnectivityFilter.h"
16
17 #include "vtkCell.h"
18 #include "vtkCellData.h"
19 #include "vtkDataSet.h"
20 #include "vtkDemandDrivenPipeline.h"
21 #include "vtkFloatArray.h"
22 #include "vtkIdList.h"
23 #include "vtkIdTypeArray.h"
24 #include "vtkInformation.h"
25 #include "vtkInformationVector.h"
26 #include "vtkMath.h"
27 #include "vtkObjectFactory.h"
28 #include "vtkPointData.h"
29 #include "vtkPoints.h"
30 #include "vtkPolyData.h"
31 #include "vtkUnstructuredGrid.h"
32
33 #include <map>
34
35 vtkObjectFactoryNewMacro(vtkConnectivityFilter);
36
37 // Construct with default extraction mode to extract largest regions.
vtkConnectivityFilter()38 vtkConnectivityFilter::vtkConnectivityFilter()
39 {
40 this->RegionSizes = vtkIdTypeArray::New();
41 this->ExtractionMode = VTK_EXTRACT_LARGEST_REGION;
42 this->ColorRegions = 0;
43 this->RegionIdAssignmentMode = UNSPECIFIED;
44
45 this->ScalarConnectivity = 0;
46 this->ScalarRange[0] = 0.0;
47 this->ScalarRange[1] = 1.0;
48
49 this->ClosestPoint[0] = this->ClosestPoint[1] = this->ClosestPoint[2] = 0.0;
50
51 this->CellScalars = vtkFloatArray::New();
52 this->CellScalars->Allocate(8);
53
54 this->NeighborCellPointIds = vtkIdList::New();
55 this->NeighborCellPointIds->Allocate(8);
56
57 this->Seeds = vtkIdList::New();
58 this->SpecifiedRegionIds = vtkIdList::New();
59
60 this->NewScalars = nullptr;
61 this->NewCellScalars = nullptr;
62
63 this->OutputPointsPrecision = vtkAlgorithm::DEFAULT_PRECISION;
64 }
65
~vtkConnectivityFilter()66 vtkConnectivityFilter::~vtkConnectivityFilter()
67 {
68 this->RegionSizes->Delete();
69 this->CellScalars->Delete();
70 this->NeighborCellPointIds->Delete();
71 this->Seeds->Delete();
72 this->SpecifiedRegionIds->Delete();
73 }
74
RequestDataObject(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)75 int vtkConnectivityFilter::RequestDataObject(vtkInformation* vtkNotUsed(request),
76 vtkInformationVector** inputVector, vtkInformationVector* outputVector)
77 {
78 vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
79 if (!inInfo)
80 {
81 return 0;
82 }
83
84 vtkDataObject* input = inInfo->Get(vtkDataObject::DATA_OBJECT());
85 if (input)
86 {
87 // for each output
88 for (int i = 0; i < this->GetNumberOfOutputPorts(); ++i)
89 {
90 vtkInformation* info = outputVector->GetInformationObject(i);
91 vtkDataObject* output = info->Get(vtkDataObject::DATA_OBJECT());
92
93 if (!output || !output->IsA(input->GetClassName()))
94 {
95 vtkDataObject* newOutput = nullptr;
96 if (input->IsA("vtkPolyData"))
97 {
98 newOutput = input->NewInstance();
99 }
100 else
101 {
102 newOutput = vtkUnstructuredGrid::New();
103 }
104
105 info->Set(vtkDataObject::DATA_OBJECT(), newOutput);
106 newOutput->Delete();
107 this->GetOutputPortInformation(0)->Set(
108 vtkDataObject::DATA_EXTENT_TYPE(), newOutput->GetExtentType());
109 }
110 }
111 return 1;
112 }
113
114 return 0;
115 }
116
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)117 int vtkConnectivityFilter::RequestData(vtkInformation* vtkNotUsed(request),
118 vtkInformationVector** inputVector, vtkInformationVector* outputVector)
119 {
120 // get the info objects
121 vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
122 vtkInformation* outInfo = outputVector->GetInformationObject(0);
123
124 // get the input and output
125 vtkDataSet* input = vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
126 vtkPointSet* output = vtkPointSet::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
127
128 vtkPolyData* pdOutput = vtkPolyData::SafeDownCast(output);
129 vtkUnstructuredGrid* ugOutput = vtkUnstructuredGrid::SafeDownCast(output);
130
131 vtkIdType numPts, numCells, cellId, i, j, pt;
132 vtkPoints* newPts;
133 vtkIdType id;
134 vtkIdType maxCellsInRegion;
135 vtkIdType largestRegionId = 0;
136 vtkPointData *pd = input->GetPointData(), *outputPD = output->GetPointData();
137 vtkCellData *cd = input->GetCellData(), *outputCD = output->GetCellData();
138
139 vtkDebugMacro(<< "Executing connectivity filter.");
140
141 // Check input/allocate storage
142 //
143 numCells = input->GetNumberOfCells();
144 if ((numPts = input->GetNumberOfPoints()) < 1 || numCells < 1)
145 {
146 vtkDebugMacro(<< "No data to connect!");
147 return 1;
148 }
149
150 if (pdOutput)
151 {
152 pdOutput->AllocateExact(numCells, 3);
153 }
154 if (ugOutput)
155 {
156 ugOutput->Allocate(numCells, numCells);
157 }
158
159 // See whether to consider scalar connectivity
160 //
161 this->InScalars = input->GetPointData()->GetScalars();
162 if (!this->ScalarConnectivity)
163 {
164 this->InScalars = nullptr;
165 }
166 else
167 {
168 if (this->ScalarRange[1] < this->ScalarRange[0])
169 {
170 this->ScalarRange[1] = this->ScalarRange[0];
171 }
172 }
173
174 // Initialize. Keep track of points and cells visited.
175 //
176 this->RegionSizes->Reset();
177 this->Visited = new vtkIdType[numCells];
178 for (i = 0; i < numCells; i++)
179 {
180 this->Visited[i] = -1;
181 }
182 this->PointMap = new vtkIdType[numPts];
183 for (i = 0; i < numPts; i++)
184 {
185 this->PointMap[i] = -1;
186 }
187
188 this->NewScalars = vtkIdTypeArray::New();
189 this->NewScalars->SetName("RegionId");
190 this->NewScalars->SetNumberOfTuples(numPts);
191
192 this->NewCellScalars = vtkIdTypeArray::New();
193 this->NewCellScalars->SetName("RegionId");
194 this->NewCellScalars->SetNumberOfTuples(numCells);
195
196 newPts = vtkPoints::New();
197
198 // Set the desired precision for the points in the output.
199 if (this->OutputPointsPrecision == vtkAlgorithm::DEFAULT_PRECISION)
200 {
201 vtkPointSet* inputPointSet = vtkPointSet::SafeDownCast(input);
202 if (inputPointSet)
203 {
204 newPts->SetDataType(inputPointSet->GetPoints()->GetDataType());
205 }
206 else
207 {
208 newPts->SetDataType(VTK_FLOAT);
209 }
210 }
211 else if (this->OutputPointsPrecision == vtkAlgorithm::SINGLE_PRECISION)
212 {
213 newPts->SetDataType(VTK_FLOAT);
214 }
215 else if (this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION)
216 {
217 newPts->SetDataType(VTK_DOUBLE);
218 }
219
220 newPts->Allocate(numPts);
221
222 // Traverse all cells marking those visited. Each new search
223 // starts a new connected region. Connected region grows
224 // using a connected wave propagation.
225 //
226 this->Wave = vtkIdList::New();
227 this->Wave->Allocate(numPts / 4 + 1, numPts);
228 this->Wave2 = vtkIdList::New();
229 this->Wave2->Allocate(numPts / 4 + 1, numPts);
230
231 this->PointNumber = 0;
232 this->RegionNumber = 0;
233 maxCellsInRegion = 0;
234
235 this->CellIds = vtkIdList::New();
236 this->CellIds->Allocate(8, VTK_CELL_SIZE);
237 this->PointIds = vtkIdList::New();
238 this->PointIds->Allocate(8, VTK_CELL_SIZE);
239
240 if (this->ExtractionMode != VTK_EXTRACT_POINT_SEEDED_REGIONS &&
241 this->ExtractionMode != VTK_EXTRACT_CELL_SEEDED_REGIONS &&
242 this->ExtractionMode != VTK_EXTRACT_CLOSEST_POINT_REGION)
243 { // visit all cells marking with region number
244 for (cellId = 0; cellId < numCells; cellId++)
245 {
246 if (cellId && !(cellId % 5000))
247 {
248 this->UpdateProgress(0.1 + 0.8 * cellId / numCells);
249 }
250
251 if (this->Visited[cellId] < 0)
252 {
253 this->NumCellsInRegion = 0;
254 this->Wave->InsertNextId(cellId);
255 this->TraverseAndMark(input);
256
257 if (this->NumCellsInRegion > maxCellsInRegion)
258 {
259 maxCellsInRegion = this->NumCellsInRegion;
260 largestRegionId = this->RegionNumber;
261 }
262
263 this->RegionSizes->InsertValue(this->RegionNumber++, this->NumCellsInRegion);
264 this->Wave->Reset();
265 this->Wave2->Reset();
266 }
267 }
268 }
269 else // regions have been seeded, everything considered in same region
270 {
271 this->NumCellsInRegion = 0;
272
273 if (this->ExtractionMode == VTK_EXTRACT_POINT_SEEDED_REGIONS)
274 {
275 for (i = 0; i < this->Seeds->GetNumberOfIds(); i++)
276 {
277 pt = this->Seeds->GetId(i);
278 if (pt >= 0)
279 {
280 input->GetPointCells(pt, this->CellIds);
281 for (j = 0; j < this->CellIds->GetNumberOfIds(); j++)
282 {
283 this->Wave->InsertNextId(this->CellIds->GetId(j));
284 }
285 }
286 }
287 }
288 else if (this->ExtractionMode == VTK_EXTRACT_CELL_SEEDED_REGIONS)
289 {
290 for (i = 0; i < this->Seeds->GetNumberOfIds(); i++)
291 {
292 cellId = this->Seeds->GetId(i);
293 if (cellId >= 0)
294 {
295 this->Wave->InsertNextId(cellId);
296 }
297 }
298 }
299 else if (this->ExtractionMode == VTK_EXTRACT_CLOSEST_POINT_REGION)
300 { // loop over points, find closest one
301 double minDist2, dist2, x[3];
302 vtkIdType minId = 0;
303 for (minDist2 = VTK_DOUBLE_MAX, i = 0; i < numPts; i++)
304 {
305 input->GetPoint(i, x);
306 dist2 = vtkMath::Distance2BetweenPoints(x, this->ClosestPoint);
307 if (dist2 < minDist2)
308 {
309 minId = i;
310 minDist2 = dist2;
311 }
312 }
313 input->GetPointCells(minId, this->CellIds);
314 for (j = 0; j < this->CellIds->GetNumberOfIds(); j++)
315 {
316 this->Wave->InsertNextId(this->CellIds->GetId(j));
317 }
318 }
319 this->UpdateProgress(0.5);
320
321 // mark all seeded regions
322 this->TraverseAndMark(input);
323 this->RegionSizes->InsertValue(this->RegionNumber, this->NumCellsInRegion);
324 this->UpdateProgress(0.9);
325 }
326
327 vtkDebugMacro(<< "Extracted " << this->RegionNumber << " region(s)");
328 this->Wave->Delete();
329 this->Wave2->Delete();
330
331 // Now that points and cells have been marked, traverse these lists pulling
332 // everything that has been visited.
333 //
334 // Pass through point data that has been visited
335 outputPD->CopyAllocate(pd);
336 outputCD->CopyAllocate(cd);
337
338 for (i = 0; i < numPts; i++)
339 {
340 if (this->PointMap[i] > -1)
341 {
342 newPts->InsertPoint(this->PointMap[i], input->GetPoint(i));
343 outputPD->CopyData(pd, i, this->PointMap[i]);
344 }
345 }
346
347 // if coloring regions; send down new scalar data
348 if (this->ColorRegions)
349 {
350 this->OrderRegionIds(this->NewScalars, this->NewCellScalars);
351
352 int idx = outputPD->AddArray(this->NewScalars);
353 outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
354 idx = outputCD->AddArray(this->NewCellScalars);
355 outputCD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);
356 }
357 this->NewScalars->Delete();
358 this->NewCellScalars->Delete();
359
360 output->SetPoints(newPts);
361 newPts->Delete();
362
363 // Create output cells
364 //
365 if (this->ExtractionMode == VTK_EXTRACT_POINT_SEEDED_REGIONS ||
366 this->ExtractionMode == VTK_EXTRACT_CELL_SEEDED_REGIONS ||
367 this->ExtractionMode == VTK_EXTRACT_CLOSEST_POINT_REGION ||
368 this->ExtractionMode == VTK_EXTRACT_ALL_REGIONS)
369 { // extract any cell that's been visited
370 for (cellId = 0; cellId < numCells; cellId++)
371 {
372 if (this->Visited[cellId] >= 0)
373 {
374 // special handling for polyhedron cells
375 if (vtkUnstructuredGrid::SafeDownCast(input) &&
376 input->GetCellType(cellId) == VTK_POLYHEDRON)
377 {
378 vtkUnstructuredGrid::SafeDownCast(input)->GetFaceStream(cellId, this->PointIds);
379 vtkUnstructuredGrid::ConvertFaceStreamPointIds(this->PointIds, this->PointMap);
380 }
381 else
382 {
383 input->GetCellPoints(cellId, this->PointIds);
384 for (i = 0; i < this->PointIds->GetNumberOfIds(); i++)
385 {
386 id = this->PointMap[this->PointIds->GetId(i)];
387 this->PointIds->InsertId(i, id);
388 }
389 }
390 vtkIdType newCellId = -1;
391 if (pdOutput)
392 {
393 newCellId = pdOutput->InsertNextCell(input->GetCellType(cellId), this->PointIds);
394 }
395 else if (ugOutput)
396 {
397 newCellId = ugOutput->InsertNextCell(input->GetCellType(cellId), this->PointIds);
398 }
399 if (newCellId >= 0)
400 {
401 outputCD->CopyData(cd, cellId, newCellId);
402 }
403 }
404 }
405 }
406 else if (this->ExtractionMode == VTK_EXTRACT_SPECIFIED_REGIONS)
407 {
408 for (cellId = 0; cellId < numCells; cellId++)
409 {
410 int inReg, regionId;
411 if ((regionId = this->Visited[cellId]) >= 0)
412 {
413 for (inReg = 0, i = 0; i < this->SpecifiedRegionIds->GetNumberOfIds(); i++)
414 {
415 if (regionId == this->SpecifiedRegionIds->GetId(i))
416 {
417 inReg = 1;
418 break;
419 }
420 }
421 if (inReg)
422 {
423 // special handling for polyhedron cells
424 if (vtkUnstructuredGrid::SafeDownCast(input) &&
425 input->GetCellType(cellId) == VTK_POLYHEDRON)
426 {
427 vtkUnstructuredGrid::SafeDownCast(input)->GetFaceStream(cellId, this->PointIds);
428 vtkUnstructuredGrid::ConvertFaceStreamPointIds(this->PointIds, this->PointMap);
429 }
430 else
431 {
432 input->GetCellPoints(cellId, this->PointIds);
433 for (i = 0; i < this->PointIds->GetNumberOfIds(); i++)
434 {
435 id = this->PointMap[this->PointIds->GetId(i)];
436 this->PointIds->InsertId(i, id);
437 }
438 }
439 vtkIdType newCellId = -1;
440 if (pdOutput)
441 {
442 newCellId = pdOutput->InsertNextCell(input->GetCellType(cellId), this->PointIds);
443 }
444 else if (ugOutput)
445 {
446 newCellId = ugOutput->InsertNextCell(input->GetCellType(cellId), this->PointIds);
447 }
448 if (newCellId >= 0)
449 {
450 outputCD->CopyData(cd, cellId, newCellId);
451 }
452 }
453 }
454 }
455 }
456 else // extract largest region
457 {
458 for (cellId = 0; cellId < numCells; cellId++)
459 {
460 if (this->Visited[cellId] == largestRegionId)
461 {
462 // special handling for polyhedron cells
463 if (vtkUnstructuredGrid::SafeDownCast(input) &&
464 input->GetCellType(cellId) == VTK_POLYHEDRON)
465 {
466 vtkUnstructuredGrid::SafeDownCast(input)->GetFaceStream(cellId, this->PointIds);
467 vtkUnstructuredGrid::ConvertFaceStreamPointIds(this->PointIds, this->PointMap);
468 }
469 else
470 {
471 input->GetCellPoints(cellId, this->PointIds);
472 for (i = 0; i < this->PointIds->GetNumberOfIds(); i++)
473 {
474 id = this->PointMap[this->PointIds->GetId(i)];
475 this->PointIds->InsertId(i, id);
476 }
477 }
478 vtkIdType newCellId = -1;
479 if (pdOutput)
480 {
481 newCellId = pdOutput->InsertNextCell(input->GetCellType(cellId), this->PointIds);
482 }
483 else if (ugOutput)
484 {
485 newCellId = ugOutput->InsertNextCell(input->GetCellType(cellId), this->PointIds);
486 }
487 if (newCellId >= 0)
488 {
489 outputCD->CopyData(cd, cellId, newCellId);
490 }
491 }
492 }
493 }
494
495 delete[] this->Visited;
496 delete[] this->PointMap;
497 this->PointIds->Delete();
498 this->CellIds->Delete();
499 output->Squeeze();
500 vtkDataArray* outScalars = nullptr;
501 if (this->ColorRegions && (outScalars = output->GetPointData()->GetScalars()))
502 {
503 outScalars->Resize(output->GetNumberOfPoints());
504 }
505
506 int num = this->GetNumberOfExtractedRegions();
507 int count = 0;
508
509 for (int ii = 0; ii < num; ii++)
510 {
511 count += this->RegionSizes->GetValue(ii);
512 }
513 vtkDebugMacro(<< "Total # of cells accounted for: " << count);
514 vtkDebugMacro(<< "Extracted " << output->GetNumberOfCells() << " cells");
515
516 return 1;
517 }
518
519 // Mark current cell as visited and assign region number. Note:
520 // traversal occurs across shared vertices.
521 //
TraverseAndMark(vtkDataSet * input)522 void vtkConnectivityFilter::TraverseAndMark(vtkDataSet* input)
523 {
524 vtkIdType i, j, k, cellId, numIds, ptId, numPts, numCells;
525 vtkIdList* tmpWave;
526
527 while ((numIds = this->Wave->GetNumberOfIds()) > 0)
528 {
529 for (i = 0; i < numIds; i++)
530 {
531 cellId = this->Wave->GetId(i);
532 if (this->Visited[cellId] < 0)
533 {
534 this->NewCellScalars->SetValue(cellId, this->RegionNumber);
535 this->Visited[cellId] = this->RegionNumber;
536 this->NumCellsInRegion++;
537 input->GetCellPoints(cellId, this->PointIds);
538
539 numPts = this->PointIds->GetNumberOfIds();
540 for (j = 0; j < numPts; j++)
541 {
542 if (this->PointMap[ptId = this->PointIds->GetId(j)] < 0)
543 {
544 this->PointMap[ptId] = this->PointNumber++;
545 this->NewScalars->SetValue(this->PointMap[ptId], this->RegionNumber);
546 }
547
548 input->GetPointCells(ptId, this->CellIds);
549
550 // check connectivity criterion (geometric + scalar)
551 numCells = this->CellIds->GetNumberOfIds();
552 for (k = 0; k < numCells; k++)
553 {
554 cellId = this->CellIds->GetId(k);
555 if (this->InScalars)
556 {
557 int numScalars, ii;
558 double s, range[2];
559
560 input->GetCellPoints(cellId, this->NeighborCellPointIds);
561 numScalars = this->NeighborCellPointIds->GetNumberOfIds();
562 this->CellScalars->SetNumberOfComponents(this->InScalars->GetNumberOfComponents());
563 this->CellScalars->SetNumberOfTuples(numScalars);
564 this->InScalars->GetTuples(this->NeighborCellPointIds, this->CellScalars);
565 range[0] = VTK_DOUBLE_MAX;
566 range[1] = -VTK_DOUBLE_MAX;
567 for (ii = 0; ii < numScalars; ii++)
568 {
569 s = this->CellScalars->GetComponent(ii, 0);
570 if (s < range[0])
571 {
572 range[0] = s;
573 }
574 if (s > range[1])
575 {
576 range[1] = s;
577 }
578 }
579 if (range[1] >= this->ScalarRange[0] && range[0] <= this->ScalarRange[1])
580 {
581 this->Wave2->InsertNextId(cellId);
582 }
583 }
584 else
585 {
586 this->Wave2->InsertNextId(cellId);
587 }
588 } // for all cells using this point
589 } // for all points of this cell
590 } // if cell not yet visited
591 } // for all cells in this wave
592
593 tmpWave = this->Wave;
594 this->Wave = this->Wave2;
595 this->Wave2 = tmpWave;
596 tmpWave->Reset();
597 } // while wave is not empty
598 }
599
OrderRegionIds(vtkIdTypeArray * pointRegionIds,vtkIdTypeArray * cellRegionIds)600 void vtkConnectivityFilter::OrderRegionIds(
601 vtkIdTypeArray* pointRegionIds, vtkIdTypeArray* cellRegionIds)
602 {
603 if (this->ColorRegions)
604 {
605 if (this->RegionIdAssignmentMode == CELL_COUNT_DESCENDING ||
606 this->RegionIdAssignmentMode == CELL_COUNT_ASCENDING)
607 {
608 // Use a multimap to handle cases where more than one region has the same number of cells.
609 std::multimap<vtkIdType, vtkIdType> cellCountToRegionId;
610 typedef std::multimap<vtkIdType, vtkIdType>::value_type ValueType;
611 vtkIdType numRegions = this->RegionSizes->GetNumberOfTuples();
612 for (vtkIdType regionId = 0; regionId < numRegions; ++regionId)
613 {
614 ValueType value(this->RegionSizes->GetValue(regionId), regionId);
615 cellCountToRegionId.insert(value);
616 }
617
618 // Now reverse iterate through the sorted multimap to process the RegionIds
619 // from largest to smallest and create a map from the old RegionId to the new
620 // RegionId
621 std::map<vtkIdType, vtkIdType> oldToNew;
622 vtkIdType counter = 0;
623 if (this->RegionIdAssignmentMode == CELL_COUNT_ASCENDING)
624 {
625 for (auto iter = cellCountToRegionId.begin(); iter != cellCountToRegionId.end(); ++iter)
626 {
627 auto regionCount = iter->first;
628 auto regionId = iter->second;
629
630 // Re-order the region sizes based on the sorting
631 this->RegionSizes->SetValue(counter, regionCount);
632
633 // Create map from old to new RegionId
634 oldToNew[regionId] = counter++;
635 }
636 }
637 else // CELL_COUNT_DESCENDING
638 {
639 for (auto iter = cellCountToRegionId.rbegin(); iter != cellCountToRegionId.rend(); ++iter)
640 {
641 auto regionCount = iter->first;
642 auto regionId = iter->second;
643
644 // Re-order the region sizes based on the sorting
645 this->RegionSizes->SetValue(counter, regionCount);
646
647 // Create map from old to new RegionId
648 oldToNew[regionId] = counter++;
649 }
650 }
651
652 vtkIdType numPts = pointRegionIds->GetNumberOfTuples();
653 for (vtkIdType i = 0; i < numPts; ++i)
654 {
655 vtkIdType oldValue = pointRegionIds->GetValue(i);
656 pointRegionIds->SetValue(i, oldToNew[oldValue]);
657 }
658
659 vtkIdType numCells = cellRegionIds->GetNumberOfTuples();
660 for (vtkIdType i = 0; i < numCells; ++i)
661 {
662 vtkIdType oldValue = cellRegionIds->GetValue(i);
663 cellRegionIds->SetValue(i, oldToNew[oldValue]);
664 }
665 }
666 // else UNSPECIFIED mode
667 }
668 }
669
670 // Obtain the number of connected regions.
GetNumberOfExtractedRegions()671 int vtkConnectivityFilter::GetNumberOfExtractedRegions()
672 {
673 return this->RegionSizes->GetMaxId() + 1;
674 }
675
ProcessRequest(vtkInformation * request,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)676 vtkTypeBool vtkConnectivityFilter::ProcessRequest(
677 vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
678 {
679 if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT()))
680 {
681 return this->RequestDataObject(request, inputVector, outputVector);
682 }
683
684 return this->Superclass::ProcessRequest(request, inputVector, outputVector);
685 }
686
687 // Initialize list of point ids/cell ids used to seed regions.
InitializeSeedList()688 void vtkConnectivityFilter::InitializeSeedList()
689 {
690 this->Modified();
691 this->Seeds->Reset();
692 }
693
694 // Add a seed id (point or cell id). Note: ids are 0-offset.
AddSeed(vtkIdType id)695 void vtkConnectivityFilter::AddSeed(vtkIdType id)
696 {
697 this->Modified();
698 this->Seeds->InsertNextId(id);
699 }
700
701 // Delete a seed id (point or cell id). Note: ids are 0-offset.
DeleteSeed(vtkIdType id)702 void vtkConnectivityFilter::DeleteSeed(vtkIdType id)
703 {
704 this->Modified();
705 this->Seeds->DeleteId(id);
706 }
707
708 // Initialize list of region ids to extract.
InitializeSpecifiedRegionList()709 void vtkConnectivityFilter::InitializeSpecifiedRegionList()
710 {
711 this->Modified();
712 this->SpecifiedRegionIds->Reset();
713 }
714
715 // Add a region id to extract. Note: ids are 0-offset.
AddSpecifiedRegion(int id)716 void vtkConnectivityFilter::AddSpecifiedRegion(int id)
717 {
718 this->Modified();
719 this->SpecifiedRegionIds->InsertNextId(id);
720 }
721
722 // Delete a region id to extract. Note: ids are 0-offset.
DeleteSpecifiedRegion(int id)723 void vtkConnectivityFilter::DeleteSpecifiedRegion(int id)
724 {
725 this->Modified();
726 this->SpecifiedRegionIds->DeleteId(id);
727 }
728
FillInputPortInformation(int,vtkInformation * info)729 int vtkConnectivityFilter::FillInputPortInformation(int, vtkInformation* info)
730 {
731 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
732 return 1;
733 }
734
FillOutputPortInformation(int vtkNotUsed (port),vtkInformation * info)735 int vtkConnectivityFilter::FillOutputPortInformation(int vtkNotUsed(port), vtkInformation* info)
736 {
737 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataSet");
738 return 1;
739 }
740
PrintSelf(ostream & os,vtkIndent indent)741 void vtkConnectivityFilter::PrintSelf(ostream& os, vtkIndent indent)
742 {
743 this->Superclass::PrintSelf(os, indent);
744
745 os << indent << "Extraction Mode: ";
746 os << this->GetExtractionModeAsString() << "\n";
747
748 os << indent << "Closest Point: (" << this->ClosestPoint[0] << ", " << this->ClosestPoint[1]
749 << ", " << this->ClosestPoint[2] << ")\n";
750
751 os << indent << "Color Regions: " << (this->ColorRegions ? "On\n" : "Off\n");
752
753 os << indent << "Scalar Connectivity: " << (this->ScalarConnectivity ? "On\n" : "Off\n");
754
755 double* range = this->GetScalarRange();
756 os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n";
757 os << indent << "Output Points Precision: " << this->OutputPointsPrecision << "\n";
758 }
759