vtkHyperOctreeSampleFunction.cxx 13.8 KB
Newer Older
Francois Bertel's avatar
Francois Bertel committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkHyperOctreeSampleFunction.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkHyperOctreeSampleFunction.h"

#include "vtkHyperOctree.h"
#include "vtkHyperOctreeCursor.h"
#include "vtkObjectFactory.h"
#include "vtkInformationVector.h"
#include "vtkInformation.h"
22
#include <cassert>
Francois Bertel's avatar
Francois Bertel committed
23
#include "vtkMath.h"
Charles Law's avatar
Charles Law committed
24
#include "vtkPointData.h"
Francois Bertel's avatar
Francois Bertel committed
25
26
27
28
29
30
31
32
33
34
35
#include "vtkDataArray.h"
#include "vtkImplicitFunction.h"
#include "vtkGarbageCollector.h"

vtkStandardNewMacro(vtkHyperOctreeSampleFunction);
vtkCxxSetObjectMacro(vtkHyperOctreeSampleFunction,ImplicitFunction,
                     vtkImplicitFunction);

//----------------------------------------------------------------------------
vtkHyperOctreeSampleFunction::vtkHyperOctreeSampleFunction()
{
David E. DeMarle's avatar
David E. DeMarle committed
36
  VTK_LEGACY_BODY(vtkHyperOctreeSampleFunction, "VTK 8.1");
37

Francois Bertel's avatar
Francois Bertel committed
38
39
40
41
  this->SetNumberOfInputPorts(0);
  this->Dimension=3;
  int i=0;
  while(i<3)
42
  {
Francois Bertel's avatar
Francois Bertel committed
43
44
45
    this->Size[i]=1;
    this->Origin[i]=0;
    ++i;
46
  }
Francois Bertel's avatar
Francois Bertel committed
47
48
  this->Levels=5;
  this->MinLevels=1;
49
  this->ImplicitFunction=nullptr;
Francois Bertel's avatar
Francois Bertel committed
50
51
52
53
54
55
56
  this->OutputScalarType=VTK_DOUBLE;
  this->Threshold=0.1;
}

//----------------------------------------------------------------------------
vtkHyperOctreeSampleFunction::~vtkHyperOctreeSampleFunction()
{
57
  this->SetImplicitFunction(nullptr);
Francois Bertel's avatar
Francois Bertel committed
58
59
60
61
62
63
64
65
66
67
68
}

//----------------------------------------------------------------------------
// Description:
// Return the maximum number of levels of the hyperoctree.
// \post positive_result: result>=1
int vtkHyperOctreeSampleFunction::GetLevels()
{
  assert("post: positive_result" && this->Levels>=1);
  return this->Levels;
}
69

Francois Bertel's avatar
Francois Bertel committed
70
71
72
73
74
75
76
77
78
79
80
81
//----------------------------------------------------------------------------
// Description:
// Set the maximum number of levels of the hyperoctree. If
// GetMinLevels()>=levels, GetMinLevels() is changed to levels-1.
// \pre positive_levels: levels>=1
// \post is_set: this->GetLevels()==levels
// \post min_is_valid: this->GetMinLevels()<this->GetLevels()
void vtkHyperOctreeSampleFunction::SetLevels(int levels)
{
  assert("pre: positive_levels" && levels>=1);
  this->Levels=levels;
  if(this->MinLevels>=levels)
82
  {
Francois Bertel's avatar
Francois Bertel committed
83
    this->MinLevels=levels-1;
84
  }
85

Francois Bertel's avatar
Francois Bertel committed
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  assert("post: is_set" && this->GetLevels()==levels);
  assert("post: min_is_valid" && this->GetMinLevels()<this->GetLevels());
}


//----------------------------------------------------------------------------
// Description:
// Return the minimal number of levels of systematic subdivision.
// \post positive_result: result>=0
int vtkHyperOctreeSampleFunction::GetMinLevels()
{
  assert("post: positive_result" && this->MinLevels>=0);
  return this->MinLevels;
}
100

Francois Bertel's avatar
Francois Bertel committed
101
102
103
104
105
106
107
108
109
110
111
//----------------------------------------------------------------------------
// Description:
// Set the minimal number of levels of systematic subdivision.
// \pre positive_minLevels: minLevels>=0 && minLevels<this->GetLevels()
// \post is_set: this->GetMinLevels()==minLevels
void vtkHyperOctreeSampleFunction::SetMinLevels(int minLevels)
{
  assert("pre: positive_minLevels" && minLevels>=0 && minLevels<this->GetLevels());
  this->MinLevels=minLevels;
  assert("post: is_set" && this->GetMinLevels()==minLevels);
}
112

Francois Bertel's avatar
Francois Bertel committed
113
114
115
116
117
118
119
120
121
//----------------------------------------------------------------------------
// Description:
// Return the threshold over which a subdivision is required.
// \post positive_result: result>0
double vtkHyperOctreeSampleFunction::GetThreshold()
{
  assert("post: positive_result" && this->Threshold>0);
  return this->Threshold;
}
122

Francois Bertel's avatar
Francois Bertel committed
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//----------------------------------------------------------------------------
// Description:
// Set the threshold over which a subdivision is required.
// \pre positive_threshold: threshold>=0
// \post is_set: this->GetThreshold()==threshold
void vtkHyperOctreeSampleFunction::SetThreshold(double threshold)
{
  assert("pre: positive_threshold" && threshold>=0);
  this->Threshold=threshold;
  assert("post: is_set" && this->GetThreshold()==threshold);
}

//-----------------------------------------------------------------------------
// Description:
// Return the dimension of the tree (1D:binary tree(2 children), 2D:quadtree
// (4 children), 3D:octree (8 children))
// \post valid_result: result>=1 && result<=3
int vtkHyperOctreeSampleFunction::GetDimension()
{
  assert("post: valid_result" && this->Dimension>=1 && this->Dimension<=3);
  return this->Dimension;
}
145

Francois Bertel's avatar
Francois Bertel committed
146
147
148
//-----------------------------------------------------------------------------
// Set the dimension of the tree with `dim'. See GetDimension() for details.
// \pre valid_dim: dim>=1 && dim<=3
149
// \post dimension_is_set: GetDimension()==dim
Francois Bertel's avatar
Francois Bertel committed
150
151
152
153
void vtkHyperOctreeSampleFunction::SetDimension(int dim)
{
  assert("pre: valid_dim" && dim>=1 && dim<=3);
  if(this->Dimension!=dim)
154
  {
Francois Bertel's avatar
Francois Bertel committed
155
156
    this->Dimension=dim;
    this->Modified();
157
  }
Francois Bertel's avatar
Francois Bertel committed
158
159
160
161
162
163
164
165
166
167
168
169
  assert("post: dimension_is_set" && this->GetDimension()==dim);
}

//-----------------------------------------------------------------------------
// Description:
// Return the length along the x-axis.
// \post positive_result: result>0
double vtkHyperOctreeSampleFunction::GetWidth()
{
  assert("post: positive_result" && this->Size[0]>0);
  return this->Size[0];
}
170

Francois Bertel's avatar
Francois Bertel committed
171
172
173
174
175
176
177
178
179
//-----------------------------------------------------------------------------
// Description:
// Set the length along the x-axis.
// \pre positive_width: width>0
// \post width_is_set: GetWidth()==width
void vtkHyperOctreeSampleFunction::SetWidth(double width)
{
  assert("pre: positive_width" && width>0);
  if(this->Size[0]!=width)
180
  {
Francois Bertel's avatar
Francois Bertel committed
181
182
    this->Size[0]=width;
    this->Modified();
183
  }
Francois Bertel's avatar
Francois Bertel committed
184
185
  assert("post: width_is_set" && this->GetWidth()==width);
}
186

Francois Bertel's avatar
Francois Bertel committed
187
188
189
190
191
192
193
194
195
196
//-----------------------------------------------------------------------------
// Description:
// Return the length along the y-axis.
// Relevant only if GetDimension()>=2
// \post positive_result: result>0
double vtkHyperOctreeSampleFunction::GetHeight()
{
  assert("post: positive_result" && this->Size[1]>0);
  return this->Size[1];
}
197

Francois Bertel's avatar
Francois Bertel committed
198
199
200
201
202
203
204
205
206
207
//-----------------------------------------------------------------------------
// Description:
// Set the length along the y-axis.
// Relevant only if GetDimension()>=2
// \pre positive_height: height>0
// \post height_is_set: GetHeight()==height
void vtkHyperOctreeSampleFunction::SetHeight(double height)
{
  assert("pre: positive_height" && height>0);
  if(this->Size[1]!=height)
208
  {
Francois Bertel's avatar
Francois Bertel committed
209
210
    this->Size[1]=height;
    this->Modified();
211
  }
Francois Bertel's avatar
Francois Bertel committed
212
213
  assert("post: height_is_set" && this->GetHeight()==height);
}
214
215


Francois Bertel's avatar
Francois Bertel committed
216
217
218
219
220
221
222
223
224
225
//-----------------------------------------------------------------------------
// Description:
// Return the length along the z-axis.
// Relevant only if GetDimension()>=3
// \post positive_result: result>0
double vtkHyperOctreeSampleFunction::GetDepth()
{
  assert("post: positive_result" && this->Size[2]>0);
  return this->Size[2];
}
226

Francois Bertel's avatar
Francois Bertel committed
227
228
229
230
231
232
233
234
235
236
//-----------------------------------------------------------------------------
// Description:
// Return the length along the z-axis.
// Relevant only if GetDimension()>=3
// \pre positive_depth: depth>0
// \post depth_is_set: GetDepth()==depth
void vtkHyperOctreeSampleFunction::SetDepth(double depth)
{
   assert("pre: positive_depth" && depth>0);
  if(this->Size[2]!=depth)
237
  {
Francois Bertel's avatar
Francois Bertel committed
238
239
    this->Size[2]=depth;
    this->Modified();
240
  }
Francois Bertel's avatar
Francois Bertel committed
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  assert("post: depth_is_set" && this->GetDepth()==depth);
}

//----------------------------------------------------------------------------
int vtkHyperOctreeSampleFunction::RequestInformation (
  vtkInformation * vtkNotUsed(request),
  vtkInformationVector ** vtkNotUsed( inputVector ),
  vtkInformationVector *outputVector)
{
  // get the info objects
  vtkInformation* outInfo = outputVector->GetInformationObject(0);

  // We cannot give the exact number of levels of the hyperoctree
  // because it is not generated yet and this process is random-based.
  // Just send an upper limit.
  // Used by the vtkHyperOctreeToUniformGrid to send some
  // whole extent in RequestInformation().
  outInfo->Set(vtkHyperOctree::LEVELS(),this->Levels);
  outInfo->Set(vtkHyperOctree::DIMENSION(),this->Dimension);
  outInfo->Set(vtkHyperOctree::SIZES(),this->Size,3);
  outInfo->Set(vtkDataObject::ORIGIN(),this->Origin,3);
262

Francois Bertel's avatar
Francois Bertel committed
263
264
265
266
267
268
269
270
271
272
273
  return 1;
}

//----------------------------------------------------------------------------
int vtkHyperOctreeSampleFunction::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **vtkNotUsed(inputVector),
  vtkInformationVector *outputVector)
{
  // get the info objects
  vtkInformation *outInfo = outputVector->GetInformationObject(0);
274

Francois Bertel's avatar
Francois Bertel committed
275
276
277
  vtkHyperOctree *output = vtkHyperOctree::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

278
  if(this->ImplicitFunction==nullptr)
279
  {
Francois Bertel's avatar
Francois Bertel committed
280
281
    vtkErrorMacro(<<"No implicit function specified");
    return 0;
282
  }
283

Francois Bertel's avatar
Francois Bertel committed
284
285
286
  output->SetDimension(this->Dimension);
  output->SetSize(this->Size);
  output->SetOrigin(this->Origin);
287

Francois Bertel's avatar
Francois Bertel committed
288
289
  vtkDataArray *scalars=vtkDataArray::CreateDataArray(this->OutputScalarType);
  scalars->SetNumberOfComponents(1);
290

291
  vtkIdType fact=static_cast<vtkIdType>(1)<<(this->Levels-1);
Francois Bertel's avatar
Francois Bertel committed
292
293
  vtkIdType maxNumberOfCells=fact;
  if(this->GetDimension()>=2)
294
  {
Francois Bertel's avatar
Francois Bertel committed
295
296
    maxNumberOfCells*=fact;
    if(this->GetDimension()==3)
297
    {
Francois Bertel's avatar
Francois Bertel committed
298
299
      maxNumberOfCells*=fact;
    }
300
  }
Francois Bertel's avatar
Francois Bertel committed
301
302
303
  scalars->Allocate(maxNumberOfCells);
  scalars->SetNumberOfTuples(1); // the root
  scalars->SetName("ImplicitFunction");
Charles Law's avatar
Charles Law committed
304
  output->GetLeafData()->SetScalars(scalars);
Francois Bertel's avatar
Francois Bertel committed
305
  scalars->UnRegister(this);
306

Francois Bertel's avatar
Francois Bertel committed
307
308
309
310
311
312
313
314
  vtkHyperOctreeCursor *cursor=output->NewCellCursor();
  cursor->ToRoot();
  this->Subdivide(cursor,1,output);
  cursor->UnRegister(this);

  scalars->Squeeze();
  assert("post: valid_levels" && output->GetNumberOfLevels()<=this->GetLevels());
  assert("post: dataset_and_data_size_match" && output->CheckAttributes()==0);
315

Francois Bertel's avatar
Francois Bertel committed
316
317
318
319
320
321
322
323
324
325
326
327
328
  return 1;
}

//----------------------------------------------------------------------------
void vtkHyperOctreeSampleFunction::Subdivide(vtkHyperOctreeCursor *cursor,
                                             int level,
                                             vtkHyperOctree *output)
{
  int subdivide=level<=this->MinLevels;
  double p[3];
  double ratio=1.0/(1<<(level-1));
  int indices[3];
  int target[3];
329

Francois Bertel's avatar
Francois Bertel committed
330
  indices[0]=cursor->GetIndex(0);
331
332
  indices[1]=0;
  indices[2]=0;
Francois Bertel's avatar
Francois Bertel committed
333
334
  p[0]=(indices[0]+0.5)*ratio*this->Size[0]+this->Origin[0];
  if(this->Dimension>1)
335
  {
Francois Bertel's avatar
Francois Bertel committed
336
337
    indices[1]=cursor->GetIndex(1);
    p[1]=(indices[1]+0.5)*ratio*this->Size[1]+this->Origin[1];
338
  }
Francois Bertel's avatar
Francois Bertel committed
339
  else
340
  {
Francois Bertel's avatar
Francois Bertel committed
341
    p[1]=this->Origin[1];
342
  }
Francois Bertel's avatar
Francois Bertel committed
343
  if(this->Dimension==3)
344
  {
Francois Bertel's avatar
Francois Bertel committed
345
346
    indices[2]=cursor->GetIndex(2);
    p[2]=(indices[2]+0.5)*ratio*this->Size[2]+this->Origin[2];
347
  }
Francois Bertel's avatar
Francois Bertel committed
348
  else
349
  {
Francois Bertel's avatar
Francois Bertel committed
350
    p[2]=this->Origin[2];
351
  }
352

Francois Bertel's avatar
Francois Bertel committed
353
  double value=this->ImplicitFunction->FunctionValue(p);
354

Francois Bertel's avatar
Francois Bertel committed
355
  if(!subdivide)
356
  {
Francois Bertel's avatar
Francois Bertel committed
357
358
    subdivide=level<this->Levels;
    if(subdivide)
359
    {
Francois Bertel's avatar
Francois Bertel committed
360
361
362
363
364
      subdivide=0;
      ratio=1.0/(1<<level);
      indices[0]<<=1; // children level
      indices[1]<<=1; // children level
      indices[2]<<=1; // children level
365

Francois Bertel's avatar
Francois Bertel committed
366
367
368
      int kc;
      int jc;
      if(this->Dimension==3)
369
      {
Francois Bertel's avatar
Francois Bertel committed
370
        kc=2;
371
      }
Francois Bertel's avatar
Francois Bertel committed
372
      else
373
      {
Francois Bertel's avatar
Francois Bertel committed
374
        kc=1;
375
      }
Francois Bertel's avatar
Francois Bertel committed
376
      if(this->Dimension>=2)
377
      {
Francois Bertel's avatar
Francois Bertel committed
378
        jc=2;
379
      }
Francois Bertel's avatar
Francois Bertel committed
380
      else
381
      {
Francois Bertel's avatar
Francois Bertel committed
382
        jc=1;
383
      }
Francois Bertel's avatar
Francois Bertel committed
384
385
      int k=0;
      while(!subdivide && k<kc)
386
      {
Francois Bertel's avatar
Francois Bertel committed
387
388
        target[2]=indices[2]+k;
        if(this->Dimension==3)
389
        {
Francois Bertel's avatar
Francois Bertel committed
390
          p[2]=(target[2]+0.5)*ratio*this->Size[2]+this->Origin[2];
391
        }
Francois Bertel's avatar
Francois Bertel committed
392
393
        int j=0;
        while(!subdivide && j<jc)
394
        {
Francois Bertel's avatar
Francois Bertel committed
395
          if(this->Dimension>1)
396
          {
Francois Bertel's avatar
Francois Bertel committed
397
398
            target[1]=indices[1]+j;
            p[1]=(target[1]+0.5)*ratio*this->Size[1]+this->Origin[1];
399
          }
Francois Bertel's avatar
Francois Bertel committed
400
401
          int i=0;
          while(!subdivide && i<2)
402
          {
Francois Bertel's avatar
Francois Bertel committed
403
404
405
406
407
408
            target[0]=indices[0]+i;
            p[0]=(target[0]+0.5)*ratio*this->Size[0]+this->Origin[0];
            double childValue=this->ImplicitFunction->FunctionValue(p);
            subdivide=fabs(value-childValue)>=this->Threshold;
            ++i;
          }
409
          ++j;
Francois Bertel's avatar
Francois Bertel committed
410
        }
411
        ++k;
Francois Bertel's avatar
Francois Bertel committed
412
413
      }
    }
414
  }
Francois Bertel's avatar
Francois Bertel committed
415
  if(subdivide)
416
  {
Francois Bertel's avatar
Francois Bertel committed
417
418
419
420
    output->SubdivideLeaf(cursor);
    int c=cursor->GetNumberOfChildren();
    int i=0;
    while(i<c)
421
    {
Francois Bertel's avatar
Francois Bertel committed
422
423
424
425
426
      cursor->ToChild(i);
      this->Subdivide(cursor,level+1,output);
      cursor->ToParent();
      ++i;
    }
427
  }
Francois Bertel's avatar
Francois Bertel committed
428
  else
429
  {
Francois Bertel's avatar
Francois Bertel committed
430
    vtkIdType id=cursor->GetLeafId();
Charles Law's avatar
Charles Law committed
431
    output->GetLeafData()->GetScalars()->InsertTuple1(id,value);
432
  }
Francois Bertel's avatar
Francois Bertel committed
433
434
435
}

//-----------------------------------------------------------------------------
Bill Lorensen's avatar
Bill Lorensen committed
436
vtkMTimeType vtkHyperOctreeSampleFunction::GetMTime()
Francois Bertel's avatar
Francois Bertel committed
437
{
Bill Lorensen's avatar
Bill Lorensen committed
438
439
  vtkMTimeType mTime=this->Superclass::GetMTime();
  vtkMTimeType impFuncMTime;
Francois Bertel's avatar
Francois Bertel committed
440

441
  if ( this->ImplicitFunction != nullptr )
442
  {
Francois Bertel's avatar
Francois Bertel committed
443
444
    impFuncMTime = this->ImplicitFunction->GetMTime();
    mTime = ( impFuncMTime > mTime ? impFuncMTime : mTime );
445
  }
Francois Bertel's avatar
Francois Bertel committed
446
447
448
449
450
451
452
453

  return mTime;
}

//-----------------------------------------------------------------------------
void vtkHyperOctreeSampleFunction::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
454

Francois Bertel's avatar
Francois Bertel committed
455
456
457
458
  os<<indent<<"Dimension: "<<Dimension<<endl;
  os<<indent<<"Width: "<<this->Size[0]<<endl;
  os<<indent<<"Height: "<<this->Size[1]<<endl;
  os<<indent<<"Depth: "<<this->Size[2]<<endl;
459

Francois Bertel's avatar
Francois Bertel committed
460
461
  os<<indent<<"origin: "<<this->Origin[0]<<","<<this->Origin[1]<<",";
  os<<this->Origin[2]<<endl;
462
463


Francois Bertel's avatar
Francois Bertel committed
464
465
466
467
468
  os<<indent<<"Levels: "<<this->Levels<<endl;
  os<<indent<<"MinLevels: "<<this->MinLevels<<endl;
  os<<indent<<"Threshold: "<<this->Threshold<<endl;
  os<<indent<<"OutputScalarType: "<<this->OutputScalarType<<endl;

469
  if(this->ImplicitFunction!=nullptr)
470
  {
Francois Bertel's avatar
Francois Bertel committed
471
    os<<indent<<"Implicit Function: "<<this->ImplicitFunction<<endl;
472
  }
Francois Bertel's avatar
Francois Bertel committed
473
  else
474
  {
Francois Bertel's avatar
Francois Bertel committed
475
    os<<indent<<"No Implicit function defined"<<endl;
476
  }
Francois Bertel's avatar
Francois Bertel committed
477
}