vtkImplicitModeller.cc 10.2 KB
Newer Older
Will Schroeder's avatar
Will Schroeder committed
1
2
/*=========================================================================

Ken Martin's avatar
Ken Martin committed
3
  Program:   Visualization Toolkit
Ken Martin's avatar
Ken Martin committed
4
  Module:    vtkImplicitModeller.cc
Will Schroeder's avatar
Will Schroeder committed
5
6
7
8
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Ken Martin's avatar
Ken Martin committed
9

Ken Martin's avatar
Ken Martin committed
10
Copyright (c) 1993-1996 Ken Martin, Will Schroeder, Bill Lorensen.
Ken Martin's avatar
Ken Martin committed
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
Will Schroeder's avatar
Will Schroeder committed
38
39
40


=========================================================================*/
Will Schroeder's avatar
Will Schroeder committed
41
#include <math.h>
Ken Martin's avatar
Ken Martin committed
42
43
#include "vtkImplicitModeller.hh"
#include "vtkFloatScalars.hh"
Will Schroeder's avatar
Will Schroeder committed
44

Will Schroeder's avatar
Will Schroeder committed
45
// Description:
46
47
48
// Construct with sample dimensions=(50,50,50), and so that model bounds are
// automatically computed from the input. Capping is turned on with CapValue
// equal to a large positive number.
Ken Martin's avatar
Ken Martin committed
49
vtkImplicitModeller::vtkImplicitModeller()
Will Schroeder's avatar
Will Schroeder committed
50
51
52
53
54
55
56
57
58
59
{
  this->MaximumDistance = 0.1;

  this->ModelBounds[0] = 0.0;
  this->ModelBounds[1] = 0.0;
  this->ModelBounds[2] = 0.0;
  this->ModelBounds[3] = 0.0;
  this->ModelBounds[4] = 0.0;
  this->ModelBounds[5] = 0.0;

Will Schroeder's avatar
Will Schroeder committed
60
61
62
  this->SampleDimensions[0] = 50;
  this->SampleDimensions[1] = 50;
  this->SampleDimensions[2] = 50;
Will Schroeder's avatar
Will Schroeder committed
63
64

  this->Capping = 1;
Will Schroeder's avatar
Will Schroeder committed
65
  this->CapValue = sqrt(VTK_LARGE_FLOAT) / 3.0;
Will Schroeder's avatar
Will Schroeder committed
66
67
}

68
69
void vtkImplicitModeller::SetModelBounds(float xmin, float xmax, float ymin, 
                                         float ymax, float zmin, float zmax)
Will Schroeder's avatar
Will Schroeder committed
70
{
71
  float bounds[6];
Will Schroeder's avatar
Will Schroeder committed
72

73
74
75
76
77
78
79
80
  bounds[0] = xmin;
  bounds[1] = xmax;
  bounds[2] = ymin;
  bounds[3] = ymax;
  bounds[4] = zmin;
  bounds[5] = zmax;

  this->SetModelBounds(bounds);
Will Schroeder's avatar
Will Schroeder committed
81
82
}

Ken Martin's avatar
Ken Martin committed
83
void vtkImplicitModeller::Execute()
Will Schroeder's avatar
Will Schroeder committed
84
{
Will Schroeder's avatar
Will Schroeder committed
85
86
  int cellNum, i, j, k;
  float *bounds, adjBounds[6];
Ken Martin's avatar
Ken Martin committed
87
  vtkCell *cell;
Will Schroeder's avatar
Will Schroeder committed
88
  float maxDistance, pcoords[3];
Ken Martin's avatar
Ken Martin committed
89
  vtkFloatScalars *newScalars;
Will Schroeder's avatar
Will Schroeder committed
90
91
92
  int numPts, idx;
  int subId;
  int min[3], max[3];
Will Schroeder's avatar
Will Schroeder committed
93
  float x[3], prevDistance2, distance2;
Will Schroeder's avatar
Will Schroeder committed
94
  int jkFactor;
Will Schroeder's avatar
Will Schroeder committed
95
  float closestPoint[3];
Ken Martin's avatar
Ken Martin committed
96
97
98
  vtkStructuredPoints *output = this->GetOutput();
  float *aspectRatio;
  float *origin;
Will Schroeder's avatar
Will Schroeder committed
99
  float *weights=new float[this->Input->GetMaxCellSize()];
Ken Martin's avatar
Ken Martin committed
100
  
Ken Martin's avatar
Ken Martin committed
101
  vtkDebugMacro(<< "Executing implicit model");
Will Schroeder's avatar
Will Schroeder committed
102

Will Schroeder's avatar
Will Schroeder committed
103
104
  numPts = this->SampleDimensions[0] * this->SampleDimensions[1] 
           * this->SampleDimensions[2];
Ken Martin's avatar
Ken Martin committed
105
  newScalars = new vtkFloatScalars(numPts);
Will Schroeder's avatar
Will Schroeder committed
106
  for (i=0; i<numPts; i++) newScalars->SetScalar(i,VTK_LARGE_FLOAT);
Will Schroeder's avatar
Will Schroeder committed
107

Ken Martin's avatar
Ken Martin committed
108
  output->SetDimensions(this->GetSampleDimensions());
Will Schroeder's avatar
Will Schroeder committed
109
  maxDistance = this->ComputeModelBounds();
Ken Martin's avatar
Ken Martin committed
110
111
112
113
114
115
  aspectRatio = output->GetAspectRatio();
  origin = output->GetOrigin();
  
  //
  // Traverse all cells; computing distance function on volume points.
  //
Will Schroeder's avatar
Will Schroeder committed
116
  for (cellNum=0; cellNum < this->Input->GetNumberOfCells(); cellNum++)
Will Schroeder's avatar
Will Schroeder committed
117
118
119
120
121
122
123
124
125
126
127
128
    {
    cell = this->Input->GetCell(cellNum);
    bounds = cell->GetBounds();
    for (i=0; i<3; i++)
      {
      adjBounds[2*i] = bounds[2*i] - maxDistance;
      adjBounds[2*i+1] = bounds[2*i+1] + maxDistance;
      }

    // compute dimensional bounds in data set
    for (i=0; i<3; i++)
      {
Ken Martin's avatar
Ken Martin committed
129
130
131
132
      min[i] = (int) ((float)(adjBounds[2*i] - origin[i]) / 
                      aspectRatio[i]);
      max[i] = (int) ((float)(adjBounds[2*i+1] - origin[i]) / 
                      aspectRatio[i]);
Will Schroeder's avatar
Will Schroeder committed
133
      if (min[i] < 0) min[i] = 0;
Will Schroeder's avatar
Will Schroeder committed
134
      if (max[i] >= this->SampleDimensions[i]) max[i] = this->SampleDimensions[i] - 1;
Will Schroeder's avatar
Will Schroeder committed
135
136
      }

Will Schroeder's avatar
Will Schroeder committed
137
138
    jkFactor = this->SampleDimensions[0]*this->SampleDimensions[1];
    for (k = min[2]; k <= max[2]; k++) 
Will Schroeder's avatar
Will Schroeder committed
139
      {
Ken Martin's avatar
Ken Martin committed
140
      x[2] = aspectRatio[2] * k + origin[2];
Will Schroeder's avatar
Will Schroeder committed
141
142
      for (j = min[1]; j <= max[1]; j++)
        {
Ken Martin's avatar
Ken Martin committed
143
        x[1] = aspectRatio[1] * j + origin[1];
Will Schroeder's avatar
Will Schroeder committed
144
145
        for (i = min[0]; i <= max[0]; i++) 
          {
Ken Martin's avatar
Ken Martin committed
146
          x[0] = aspectRatio[0] * i + origin[0];
Will Schroeder's avatar
Will Schroeder committed
147
          idx = jkFactor*k + this->SampleDimensions[0]*j + i;
Will Schroeder's avatar
Will Schroeder committed
148
          prevDistance2 = newScalars->GetScalar(idx);
149
150
151
152

          // union combination of distances
          if ( cell->EvaluatePosition(x, closestPoint, subId, pcoords, 
          distance2, weights) != -1 && distance2 < prevDistance2 )
Will Schroeder's avatar
Will Schroeder committed
153
            newScalars->SetScalar(idx,distance2);
Will Schroeder's avatar
Will Schroeder committed
154
155
156
157
158
          }
        }
      }
    }
//
Will Schroeder's avatar
Will Schroeder committed
159
160
161
162
163
164
165
166
// Run through scalars and take square root
//
  for (i=0; i<numPts; i++)
    {
    distance2 = newScalars->GetScalar(i);
    newScalars->SetScalar(i,sqrt(distance2));
    }
//
Will Schroeder's avatar
Will Schroeder committed
167
168
169
170
171
172
173
174
// If capping is turned on, set the distances of the outside of the volume
// to the CapValue.
//
  if ( this->Capping )
    {
    this->Cap(newScalars);
    }
//
Will Schroeder's avatar
Will Schroeder committed
175
// Update self and release memory
Will Schroeder's avatar
Will Schroeder committed
176
//
Ken Martin's avatar
Ken Martin committed
177
  output->GetPointData()->SetScalars(newScalars);
Will Schroeder's avatar
Will Schroeder committed
178
  newScalars->Delete();
Will Schroeder's avatar
Will Schroeder committed
179
  delete [] weights;
Will Schroeder's avatar
Will Schroeder committed
180
181
}

Will Schroeder's avatar
Will Schroeder committed
182
183
// Description:
// Compute ModelBounds from input geometry.
Ken Martin's avatar
Ken Martin committed
184
float vtkImplicitModeller::ComputeModelBounds()
Will Schroeder's avatar
Will Schroeder committed
185
{
Will Schroeder's avatar
Will Schroeder committed
186
187
  float *bounds, maxDist;
  int i, adjustBounds=0;
Ken Martin's avatar
Ken Martin committed
188
189
190
  vtkStructuredPoints *output = this->GetOutput();
  float tempf[3];
  
Will Schroeder's avatar
Will Schroeder committed
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
  // compute model bounds if not set previously
  if ( this->ModelBounds[0] >= this->ModelBounds[1] ||
  this->ModelBounds[2] >= this->ModelBounds[3] ||
  this->ModelBounds[4] >= this->ModelBounds[5] )
    {
    adjustBounds = 1;
    bounds = this->Input->GetBounds();
    }
  else
    {
    bounds = this->ModelBounds;
    }

  for (maxDist=0.0, i=0; i<3; i++)
    if ( (bounds[2*i+1] - bounds[2*i]) > maxDist )
      maxDist = bounds[2*i+1] - bounds[2*i];

  maxDist *= this->MaximumDistance;

  // adjust bounds so model fits strictly inside (only if not set previously)
  if ( adjustBounds )
    {
    for (i=0; i<3; i++)
      {
      this->ModelBounds[2*i] = bounds[2*i] - maxDist;
      this->ModelBounds[2*i+1] = bounds[2*i+1] + maxDist;
      }
    }

  // Set volume origin and aspect ratio
Ken Martin's avatar
Ken Martin committed
221
222
223
  output->SetOrigin(this->ModelBounds[0],this->ModelBounds[2],
		    this->ModelBounds[4]);
  
Will Schroeder's avatar
Will Schroeder committed
224
225
  for (i=0; i<3; i++)
    {
Ken Martin's avatar
Ken Martin committed
226
227
    tempf[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i])
      / (this->SampleDimensions[i] - 1);
Will Schroeder's avatar
Will Schroeder committed
228
    }
Ken Martin's avatar
Ken Martin committed
229
  output->SetAspectRatio(tempf);
Will Schroeder's avatar
Will Schroeder committed
230
231

  return maxDist;  
Will Schroeder's avatar
Will Schroeder committed
232
}
Will Schroeder's avatar
Will Schroeder committed
233

Will Schroeder's avatar
Will Schroeder committed
234
235
// Description:
// Set the i-j-k dimensions on which to sample the distance function.
Ken Martin's avatar
Ken Martin committed
236
void vtkImplicitModeller::SetSampleDimensions(int i, int j, int k)
Will Schroeder's avatar
Will Schroeder committed
237
238
239
240
241
242
243
244
245
246
{
  int dim[3];

  dim[0] = i;
  dim[1] = j;
  dim[2] = k;

  this->SetSampleDimensions(dim);
}

Ken Martin's avatar
Ken Martin committed
247
void vtkImplicitModeller::SetSampleDimensions(int dim[3])
Will Schroeder's avatar
Will Schroeder committed
248
{
Will Schroeder's avatar
Will Schroeder committed
249
250
  int dataDim, i;

Ken Martin's avatar
Ken Martin committed
251
  vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")");
Will Schroeder's avatar
Will Schroeder committed
252
253
254
255
256
257

  if ( dim[0] != this->SampleDimensions[0] || dim[1] != SampleDimensions[1] ||
  dim[2] != SampleDimensions[2] )
    {
    if ( dim[0]<1 || dim[1]<1 || dim[2]<1 )
      {
Ken Martin's avatar
Ken Martin committed
258
      vtkErrorMacro (<< "Bad Sample Dimensions, retaining previous values");
Will Schroeder's avatar
Will Schroeder committed
259
260
261
      return;
      }

Will Schroeder's avatar
Will Schroeder committed
262
    for (dataDim=0, i=0; i<3 ; i++) if (dim[i] > 1) dataDim++;
Will Schroeder's avatar
Will Schroeder committed
263
264
265

    if ( dataDim  < 3 )
      {
Ken Martin's avatar
Ken Martin committed
266
      vtkErrorMacro(<<"Sample dimensions must define a volume!");
Will Schroeder's avatar
Will Schroeder committed
267
268
269
270
271
272
273
274
      return;
      }

    for ( i=0; i<3; i++) this->SampleDimensions[i] = dim[i];

    this->Modified();
    }
}
Will Schroeder's avatar
Will Schroeder committed
275

Ken Martin's avatar
Ken Martin committed
276
void vtkImplicitModeller::Cap(vtkFloatScalars *s)
Will Schroeder's avatar
Will Schroeder committed
277
278
279
280
281
282
283
284
285
{
  int i,j,k;
  int idx;
  int d01=this->SampleDimensions[0]*this->SampleDimensions[1];

// i-j planes
  k = 0;
  for (j=0; j<this->SampleDimensions[1]; j++)
    for (i=0; i<this->SampleDimensions[0]; i++)
Will Schroeder's avatar
Will Schroeder committed
286
      s->SetScalar(i+j*this->SampleDimensions[0], this->CapValue);
Will Schroeder's avatar
Will Schroeder committed
287
288
289
290
291

  k = this->SampleDimensions[2] - 1;
  idx = k*d01;
  for (j=0; j<this->SampleDimensions[1]; j++)
    for (i=0; i<this->SampleDimensions[0]; i++)
Will Schroeder's avatar
Will Schroeder committed
292
      s->SetScalar(idx+i+j*this->SampleDimensions[0], this->CapValue);
Will Schroeder's avatar
Will Schroeder committed
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

// j-k planes
  i = 0;
  for (k=0; k<this->SampleDimensions[2]; k++)
    for (j=0; j<this->SampleDimensions[1]; j++)
      s->SetScalar(j*this->SampleDimensions[0]+k*d01, this->CapValue);

  i = this->SampleDimensions[0] - 1;
  for (k=0; k<this->SampleDimensions[2]; k++)
    for (j=0; j<this->SampleDimensions[1]; j++)
      s->SetScalar(i+j*this->SampleDimensions[0]+k*d01, this->CapValue);

// i-k planes
  j = 0;
  for (k=0; k<this->SampleDimensions[2]; k++)
    for (i=0; i<this->SampleDimensions[0]; i++)
      s->SetScalar(i+k*d01, this->CapValue);

  j = this->SampleDimensions[1] - 1;
  idx = j*this->SampleDimensions[0];
  for (k=0; k<this->SampleDimensions[2]; k++)
    for (i=0; i<this->SampleDimensions[0]; i++)
      s->SetScalar(idx+i+k*d01, this->CapValue);

}

Will Schroeder's avatar
Will Schroeder committed
319
320
321
void vtkImplicitModeller::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToStructuredPointsFilter::PrintSelf(os,indent);
Will Schroeder's avatar
Will Schroeder committed
322

Will Schroeder's avatar
Will Schroeder committed
323
324
325
326
327
328
329
330
331
332
333
334
  os << indent << "Maximum Distance: " << this->MaximumDistance << "\n";
  os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", "
               << this->SampleDimensions[1] << ", "
               << this->SampleDimensions[2] << ")\n";
  os << indent << "ModelBounds: \n";
  os << indent << "  Xmin,Xmax: (" << this->ModelBounds[0] << ", " << this->ModelBounds[1] << ")\n";
  os << indent << "  Ymin,Ymax: (" << this->ModelBounds[2] << ", " << this->ModelBounds[3] << ")\n";
  os << indent << "  Zmin,Zmax: (" << this->ModelBounds[4] << ", " << this->ModelBounds[5] << ")\n";

  os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
  os << indent << "Cap Value: " << this->CapValue << "\n";
}