vtkExtractPolyDataGeometry.cxx 10.7 KB
Newer Older
Will Schroeder's avatar
Will Schroeder committed
1 2 3 4 5
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkExtractPolyDataGeometry.cxx

6
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 8
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
Will Schroeder's avatar
Will Schroeder committed
9

10 11
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12
     PURPOSE.  See the above copyright notice for more information.
Will Schroeder's avatar
Will Schroeder committed
13 14 15

=========================================================================*/
#include "vtkExtractPolyDataGeometry.h"
16

17 18
#include "vtkCellArray.h"
#include "vtkCellData.h"
19
#include "vtkFloatArray.h"
20
#include "vtkImplicitFunction.h"
21 22
#include "vtkInformation.h"
#include "vtkInformationVector.h"
23
#include "vtkObjectFactory.h"
24
#include "vtkPointData.h"
25
#include "vtkPolyData.h"
26

Brad King's avatar
Brad King committed
27
vtkStandardNewMacro(vtkExtractPolyDataGeometry);
28 29
vtkCxxSetObjectMacro(vtkExtractPolyDataGeometry,
                     ImplicitFunction,vtkImplicitFunction);
30

31
//----------------------------------------------------------------------------
Will Schroeder's avatar
Will Schroeder committed
32 33 34 35 36
// Construct object with ExtractInside turned on.
vtkExtractPolyDataGeometry::vtkExtractPolyDataGeometry(vtkImplicitFunction *f)
{
  this->ImplicitFunction = f;
  if (this->ImplicitFunction)
37
  {
Will Schroeder's avatar
Will Schroeder committed
38
    this->ImplicitFunction->Register(this);
39
  }
40

Will Schroeder's avatar
Will Schroeder committed
41
  this->ExtractInside = 1;
42
  this->ExtractBoundaryCells = 0;
43
  this->PassPoints = 0;
Will Schroeder's avatar
Will Schroeder committed
44 45
}

46
//----------------------------------------------------------------------------
Will Schroeder's avatar
Will Schroeder committed
47 48
vtkExtractPolyDataGeometry::~vtkExtractPolyDataGeometry()
{
49
  this->SetImplicitFunction(nullptr);
Will Schroeder's avatar
Will Schroeder committed
50 51
}

52
//----------------------------------------------------------------------------
Will Schroeder's avatar
Will Schroeder committed
53 54
// Overload standard modified time function. If implicit function is modified,
// then this object is modified as well.
Bill Lorensen's avatar
Bill Lorensen committed
55
vtkMTimeType vtkExtractPolyDataGeometry::GetMTime()
Will Schroeder's avatar
Will Schroeder committed
56
{
Bill Lorensen's avatar
Bill Lorensen committed
57 58
  vtkMTimeType mTime=this->MTime.GetMTime();
  vtkMTimeType impFuncMTime;
Will Schroeder's avatar
Will Schroeder committed
59

60
  if ( this->ImplicitFunction != nullptr )
61
  {
Will Schroeder's avatar
Will Schroeder committed
62 63
    impFuncMTime = this->ImplicitFunction->GetMTime();
    mTime = ( impFuncMTime > mTime ? impFuncMTime : mTime );
64
  }
Will Schroeder's avatar
Will Schroeder committed
65 66 67 68

  return mTime;
}

69
//----------------------------------------------------------------------------
70 71 72 73
int vtkExtractPolyDataGeometry::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
Will Schroeder's avatar
Will Schroeder committed
74
{
75 76 77 78
  // get the info objects
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

79
  // get the input and output
80 81 82 83 84
  vtkPolyData *input = vtkPolyData::SafeDownCast(
    inInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkPolyData *output = vtkPolyData::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

Will Schroeder's avatar
Will Schroeder committed
85 86 87 88
  vtkPointData *pd = input->GetPointData();
  vtkCellData *cd = input->GetCellData();
  vtkPointData *outputPD = output->GetPointData();
  vtkCellData *outputCD = output->GetCellData();
89
  vtkPoints *inPts=input->GetPoints();
90
  vtkIdType numPts, i, cellId = 0, newId, ptId, *pointMap=nullptr;
91
  float multiplier;
92 93 94
  vtkCellArray *inVerts=nullptr, *inLines=nullptr, *inPolys=nullptr, *inStrips=nullptr;
  vtkCellArray *newVerts=nullptr, *newLines=nullptr, *newPolys=nullptr, *newStrips=nullptr;
  vtkPoints *newPts=nullptr;
Will Schroeder's avatar
Will Schroeder committed
95 96 97 98

  vtkDebugMacro(<< "Extracting poly data geometry");

  if ( ! this->ImplicitFunction )
99
  {
Will Schroeder's avatar
Will Schroeder committed
100
    vtkErrorMacro(<<"No implicit function specified");
101
    return 1;
102
  }
Will Schroeder's avatar
Will Schroeder committed
103

104 105
  numPts = input->GetNumberOfPoints();

Will Schroeder's avatar
Will Schroeder committed
106
  if ( this->ExtractInside )
107
  {
Will Schroeder's avatar
Will Schroeder committed
108
    multiplier = 1.0;
109
  }
110
  else
111
  {
Will Schroeder's avatar
Will Schroeder committed
112
    multiplier = -1.0;
113
  }
Will Schroeder's avatar
Will Schroeder committed
114

115 116 117 118 119
  // Use a templated function to access the points. The points are
  // passed through, but scalar values are generated.
  vtkFloatArray *newScalars = vtkFloatArray::New();
  newScalars->SetNumberOfValues(numPts);

120
  for (ptId=0; ptId < numPts; ptId++ )
121
  {
122 123
    newScalars->SetValue(ptId, this->ImplicitFunction->
                         FunctionValue(inPts->GetPoint(ptId))*multiplier);
124
  }
Will Schroeder's avatar
Will Schroeder committed
125

126 127
  // Do different things with the points depending on user directive
  if ( this->PassPoints )
128
  {
129 130
    output->SetPoints(inPts);
    outputPD->PassData(pd);
131
  }
132
  else
133
  {
134 135 136 137
    newPts = vtkPoints::New();
    newPts->Allocate(numPts/4,numPts);
    pointMap = new vtkIdType[numPts]; // maps old point ids into new
    for (ptId=0; ptId < numPts; ptId++)
138
    {
139
      if ( newScalars->GetValue(ptId) <= 0.0 )
140
      {
141
        newId = this->InsertPointInMap(ptId, inPts, newPts, pointMap);
142
      }
143
      else
144
      {
145 146 147
        pointMap[ptId] = -1;
      }
    }
148
  }
149
  outputCD->CopyAllocate(cd);
150 151 152 153 154 155 156

  // Now loop over all cells to see whether they are inside the implicit
  // function. Copy if they are. Note: there is an awful hack here, that
  // can result in bugs. The cellId is assumed to be arranged starting
  // with the verts, then lines, then polys, then strips.
  //
  int numIn;
157
  vtkIdType npts = 0;
158
  vtkIdType *pts = nullptr;
159
  if ( input->GetNumberOfVerts() )
160
  {
161 162 163
    inVerts = input->GetVerts();
    newVerts = vtkCellArray::New();
    newVerts->Allocate(inVerts->GetSize());
164
  }
165
  if ( input->GetNumberOfLines() )
166
  {
167 168 169
    inLines = input->GetLines();
    newLines = vtkCellArray::New();
    newLines->Allocate(inLines->GetSize());
170
  }
171
  if ( input->GetNumberOfPolys() )
172
  {
173 174 175
    inPolys = input->GetPolys();
    newPolys = vtkCellArray::New();
    newPolys->Allocate(inPolys->GetSize());
176
  }
177
  if ( input->GetNumberOfStrips() )
178
  {
179 180 181
    inStrips = input->GetStrips();
    newStrips = vtkCellArray::New();
    newStrips->Allocate(inStrips->GetSize());
182
  }
183

184 185
  // verts
  if ( newVerts && !this->GetAbortExecute() )
186
  {
187
    for (inVerts->InitTraversal(); inVerts->GetNextCell(npts,pts); )
188
    {
189
      for (numIn=0, i=0; i<npts; i++)
190
      {
191
        if ( newScalars->GetValue(pts[i]) <= 0.0 )
192
        {
193 194
          numIn++;
        }
195
      }
196
      if ( (numIn == npts) || (this->ExtractBoundaryCells && numIn > 0) )
197
      {
198
        if ( this->PassPoints )
199
        {
200
          newId = newVerts->InsertNextCell(npts,pts);
201
        }
202
        else
203
        {
204 205
          newId = newVerts->InsertNextCell(npts);
          for ( i=0; i < npts; i++)
206
          {
207
            if ( pointMap[pts[i]] < 0 )
208
            {
209
              ptId = this->InsertPointInMap(pts[i], inPts, newPts, pointMap);
210
            }
211
            else
212
            {
213 214
              ptId = pointMap[pts[i]];
            }
215
            newVerts->InsertCellPoint(ptId);
216
          }
217
        }
218
        outputCD->CopyData(cd, cellId, newId);
Will Schroeder's avatar
Will Schroeder committed
219
      }
220
      cellId++;
Will Schroeder's avatar
Will Schroeder committed
221
    }
222
  }
223
  this->UpdateProgress (0.6);
Will Schroeder's avatar
Will Schroeder committed
224

225 226
  // lines
  if ( newLines && !this->GetAbortExecute() )
227
  {
228
    for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); )
229
    {
230
      for (numIn=0, i=0; i<npts; i++)
231
      {
232
        if ( newScalars->GetValue(pts[i]) <= 0.0 )
233
        {
234 235
          numIn++;
        }
236
      }
237
      if ( (numIn == npts) || (this->ExtractBoundaryCells && numIn > 0) )
238
      {
239
        if ( this->PassPoints )
240
        {
241
          newId = newLines->InsertNextCell(npts,pts);
242
        }
243
        else
244
        {
245 246
          newId = newLines->InsertNextCell(npts);
          for ( i=0; i < npts; i++)
247
          {
248
            if ( pointMap[pts[i]] < 0 )
249
            {
250
              ptId = this->InsertPointInMap(pts[i], inPts, newPts, pointMap);
251
            }
252
            else
253
            {
254 255
              ptId = pointMap[pts[i]];
            }
256
            newLines->InsertCellPoint(ptId);
257
          }
258
        }
259
        outputCD->CopyData(cd, cellId, newId);
260
      }
261
      cellId++;
Will Schroeder's avatar
Will Schroeder committed
262
    }
263
  }
264
  this->UpdateProgress (0.75);
265

266 267
  // polys
  if ( newPolys && !this->GetAbortExecute() )
268
  {
269
    for (inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); )
270
    {
271
      for (numIn=0, i=0; i<npts; i++)
272
      {
273
        if ( newScalars->GetValue(pts[i]) <= 0.0 )
274
        {
275
          numIn++;
Will Schroeder's avatar
Will Schroeder committed
276
        }
277
      }
278
      if ( (numIn == npts) || (this->ExtractBoundaryCells && numIn > 0) )
279
      {
280
        if ( this->PassPoints )
281
        {
282
          newId = newPolys->InsertNextCell(npts,pts);
283
        }
284
        else
285
        {
286 287
          newId = newPolys->InsertNextCell(npts);
          for ( i=0; i < npts; i++)
288
          {
289
            if ( pointMap[pts[i]] < 0 )
290
            {
291
              ptId = this->InsertPointInMap(pts[i], inPts, newPts, pointMap);
292
            }
293
            else
294
            {
295 296
              ptId = pointMap[pts[i]];
            }
297
            newPolys->InsertCellPoint(ptId);
298
          }
299
        }
300
        outputCD->CopyData(cd, cellId, newId);
Will Schroeder's avatar
Will Schroeder committed
301
      }
302
      cellId++;
303
    }
304
  }
305
  this->UpdateProgress (0.90);
306

307 308
  // strips
  if ( newStrips && !this->GetAbortExecute() )
309
  {
310
    for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); )
311
    {
312
      for (numIn=0, i=0; i<npts; i++)
313
      {
314
        if ( newScalars->GetValue(pts[i]) <= 0.0 )
315
        {
316 317
          numIn++;
        }
318
      }
319
      if ( (numIn == npts) || (this->ExtractBoundaryCells && numIn > 0) )
320
      {
321
        if ( this->PassPoints )
322
        {
323
          newId = newStrips->InsertNextCell(npts,pts);
324
        }
325
        else
326
        {
327 328
          newId = newStrips->InsertNextCell(npts);
          for ( i=0; i < npts; i++)
329
          {
330
            if ( pointMap[pts[i]] < 0 )
331
            {
332
              ptId = this->InsertPointInMap(pts[i], inPts, newPts, pointMap);
333
            }
334
            else
335
            {
336 337
              ptId = pointMap[pts[i]];
            }
338
            newStrips->InsertCellPoint(ptId);
339
          }
340
        }
341
        outputCD->CopyData(cd, cellId, newId);
Will Schroeder's avatar
Will Schroeder committed
342
      }
343
      cellId++;
344
    }
345
  }
346
  this->UpdateProgress (1.0);
347

Will Schroeder's avatar
Will Schroeder committed
348 349
  // Update ourselves and release memory
  //
350
  newScalars->Delete();
351
  if ( ! this->PassPoints )
352
  {
353 354 355 356
    output->SetPoints(newPts);
    newPts->Delete();
    outputPD->CopyAllocate(pd);
    for (i=0; i < numPts; i++)
357
    {
358
      if ( pointMap[i] >= 0 )
359
      {
360 361 362
        outputPD->CopyData(pd,i,pointMap[i]);
      }
    }
363 364
    delete [] pointMap;
  }
Will Schroeder's avatar
Will Schroeder committed
365

366
  if ( newVerts )
367
  {
368 369
    output->SetVerts(newVerts);
    newVerts->Delete();
370
  }
371
  if ( newLines )
372
  {
373 374
    output->SetLines(newLines);
    newLines->Delete();
375
  }
376
  if ( newPolys )
377
  {
378 379
    output->SetPolys(newPolys);
    newPolys->Delete();
380
  }
381
  if ( newStrips )
382
  {
383 384
    output->SetStrips(newStrips);
    newStrips->Delete();
385
  }
386 387

  return 1;
Will Schroeder's avatar
Will Schroeder committed
388 389
}

390
//----------------------------------------------------------------------------
391
void vtkExtractPolyDataGeometry::PrintSelf(ostream& os, vtkIndent indent)
Will Schroeder's avatar
Will Schroeder committed
392
{
Brad King's avatar
Brad King committed
393
  this->Superclass::PrintSelf(os,indent);
Will Schroeder's avatar
Will Schroeder committed
394

395
  if (this->ImplicitFunction)
396
  {
397
    os << indent << "Implicit Function: "
398
       << static_cast<void *>(this->ImplicitFunction) << "\n";
399
  }
400
  else
401
  {
402
    os << indent << "Implicit Function: (null)\n";
403
  }
404
  os << indent << "Extract Inside: "
Will Schroeder's avatar
Will Schroeder committed
405
     << (this->ExtractInside ? "On\n" : "Off\n");
406
  os << indent << "Extract Boundary Cells: "
407
     << (this->ExtractBoundaryCells ? "On\n" : "Off\n");
408 409
  os << indent << "Pass Points: "
     << (this->PassPoints ? "On\n" : "Off\n");
Will Schroeder's avatar
Will Schroeder committed
410
}