vtkImplicitModeller.cc 10.7 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
10
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

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

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>
Will Schroeder's avatar
Will Schroeder committed
42
#include "ImpMod.hh"
Will Schroeder's avatar
Will Schroeder committed
43
#include "FScalars.hh"
Will Schroeder's avatar
Will Schroeder committed
44

Will Schroeder's avatar
Will Schroeder committed
45
46
47
48
// Description:
// Construct with sample dimensions=(50,50,50) and so that model bounds are
// automatically computer from 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
65

  this->Capping = 1;
  this->CapValue = LARGE_FLOAT;
Will Schroeder's avatar
Will Schroeder committed
66
67
}

Will Schroeder's avatar
Will Schroeder committed
68
69
// Description:
// Specify the position in space to perform the sampling.
Ken Martin's avatar
Ken Martin committed
70
void vtkImplicitModeller::SetModelBounds(float *bounds)
Will Schroeder's avatar
Will Schroeder committed
71
{
Ken Martin's avatar
Ken Martin committed
72
  vtkImplicitModeller::SetModelBounds(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
Will Schroeder's avatar
Will Schroeder committed
73
74
}

Ken Martin's avatar
Ken Martin committed
75
void vtkImplicitModeller::SetModelBounds(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax)
Will Schroeder's avatar
Will Schroeder committed
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
{
  if (this->ModelBounds[0] != xmin || this->ModelBounds[1] != xmax ||
  this->ModelBounds[2] != ymin || this->ModelBounds[3] != ymax ||
  this->ModelBounds[4] != zmin || this->ModelBounds[5] != zmax )
    {
    float length;

    this->Modified();
    this->ModelBounds[0] = xmin;
    this->ModelBounds[1] = xmax;
    this->ModelBounds[2] = ymin;
    this->ModelBounds[3] = ymax;
    this->ModelBounds[4] = zmin;
    this->ModelBounds[5] = zmax;

    this->Origin[0] = xmin;
    this->Origin[1] = ymin;
    this->Origin[2] = zmin;

Will Schroeder's avatar
Will Schroeder committed
95
    if ( (length = xmax - xmin) == 0.0 ) length = 1.0;
Will Schroeder's avatar
Will Schroeder committed
96
97
98
99
100
101
    this->AspectRatio[0] = 1.0;
    this->AspectRatio[1] = (ymax - ymin) / length;
    this->AspectRatio[2] = (zmax - zmin) / length;
    }
}

Ken Martin's avatar
Ken Martin committed
102
void vtkImplicitModeller::Execute()
Will Schroeder's avatar
Will Schroeder committed
103
{
Will Schroeder's avatar
Will Schroeder committed
104
105
  int cellNum, i, j, k;
  float *bounds, adjBounds[6];
Ken Martin's avatar
Ken Martin committed
106
  vtkCell *cell;
Will Schroeder's avatar
Will Schroeder committed
107
  float maxDistance, pcoords[3];
Ken Martin's avatar
Ken Martin committed
108
  vtkFloatScalars *newScalars;
Will Schroeder's avatar
Will Schroeder committed
109
110
111
  int numPts, idx;
  int subId;
  int min[3], max[3];
Will Schroeder's avatar
Will Schroeder committed
112
  float x[3], prevDistance2, distance2;
Will Schroeder's avatar
Will Schroeder committed
113
  int jkFactor;
Will Schroeder's avatar
Will Schroeder committed
114
  float weights[MAX_CELL_SIZE];
Will Schroeder's avatar
Will Schroeder committed
115
  float closestPoint[3];
Will Schroeder's avatar
Will Schroeder committed
116

Ken Martin's avatar
Ken Martin committed
117
  vtkDebugMacro(<< "Executing implicit model");
Will Schroeder's avatar
Will Schroeder committed
118
119
  this->Initialize();

Will Schroeder's avatar
Will Schroeder committed
120
121
  numPts = this->SampleDimensions[0] * this->SampleDimensions[1] 
           * this->SampleDimensions[2];
Ken Martin's avatar
Ken Martin committed
122
  newScalars = new vtkFloatScalars(numPts);
Will Schroeder's avatar
Will Schroeder committed
123
  for (i=0; i<numPts; i++) newScalars->SetScalar(i,LARGE_FLOAT);
Will Schroeder's avatar
Will Schroeder committed
124

Will Schroeder's avatar
Will Schroeder committed
125
  this->SetDimensions(this->GetSampleDimensions());
Will Schroeder's avatar
Will Schroeder committed
126
127
128
129
  maxDistance = this->ComputeModelBounds();
//
// Traverse all cells; computing distance function on volume points.
//
Will Schroeder's avatar
Will Schroeder committed
130
  for (cellNum=0; cellNum < this->Input->GetNumberOfCells(); cellNum++)
Will Schroeder's avatar
Will Schroeder committed
131
132
133
134
135
136
137
138
139
140
141
142
    {
    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++)
      {
143
144
145
146
      min[i] = (int) ((float)(adjBounds[2*i] - this->Origin[i]) / 
                      this->AspectRatio[i]);
      max[i] = (int) ((float)(adjBounds[2*i+1] - this->Origin[i]) / 
                      this->AspectRatio[i]);
Will Schroeder's avatar
Will Schroeder committed
147
      if (min[i] < 0) min[i] = 0;
Will Schroeder's avatar
Will Schroeder committed
148
      if (max[i] >= this->SampleDimensions[i]) max[i] = this->SampleDimensions[i] - 1;
Will Schroeder's avatar
Will Schroeder committed
149
150
      }

Will Schroeder's avatar
Will Schroeder committed
151
152
    jkFactor = this->SampleDimensions[0]*this->SampleDimensions[1];
    for (k = min[2]; k <= max[2]; k++) 
Will Schroeder's avatar
Will Schroeder committed
153
154
155
156
157
158
159
160
      {
      x[2] = this->AspectRatio[2] * k + this->Origin[2];
      for (j = min[1]; j <= max[1]; j++)
        {
        x[1] = this->AspectRatio[1] * j + this->Origin[1];
        for (i = min[0]; i <= max[0]; i++) 
          {
          x[0] = this->AspectRatio[0] * i + this->Origin[0];
Will Schroeder's avatar
Will Schroeder committed
161
          idx = jkFactor*k + this->SampleDimensions[0]*j + i;
Will Schroeder's avatar
Will Schroeder committed
162
          prevDistance2 = newScalars->GetScalar(idx);
163
164
165
166

          // union combination of distances
          if ( cell->EvaluatePosition(x, closestPoint, subId, pcoords, 
          distance2, weights) != -1 && distance2 < prevDistance2 )
Will Schroeder's avatar
Will Schroeder committed
167
            newScalars->SetScalar(idx,distance2);
Will Schroeder's avatar
Will Schroeder committed
168
169
170
171
172
          }
        }
      }
    }
//
Will Schroeder's avatar
Will Schroeder committed
173
174
175
176
177
178
179
180
// 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
181
182
183
184
185
186
187
188
// 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
189
// Update self and release memory
Will Schroeder's avatar
Will Schroeder committed
190
191
//
  this->PointData.SetScalars(newScalars);
Will Schroeder's avatar
Will Schroeder committed
192
  newScalars->Delete();
Will Schroeder's avatar
Will Schroeder committed
193
194
}

Will Schroeder's avatar
Will Schroeder committed
195
196
// Description:
// Compute ModelBounds from input geometry.
Ken Martin's avatar
Ken Martin committed
197
float vtkImplicitModeller::ComputeModelBounds()
Will Schroeder's avatar
Will Schroeder committed
198
{
Will Schroeder's avatar
Will Schroeder committed
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  float *bounds, maxDist;
  int i, adjustBounds=0;

  // 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
  for (i=0; i<3; i++)
    {
    this->Origin[i] = this->ModelBounds[2*i];
Will Schroeder's avatar
Will Schroeder committed
235
236
    this->AspectRatio[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i])
                           / (this->SampleDimensions[i] - 1);
Will Schroeder's avatar
Will Schroeder committed
237
238
239
    }

  return maxDist;  
Will Schroeder's avatar
Will Schroeder committed
240
}
Will Schroeder's avatar
Will Schroeder committed
241

Will Schroeder's avatar
Will Schroeder committed
242
243
// Description:
// Set the i-j-k dimensions on which to sample the distance function.
Ken Martin's avatar
Ken Martin committed
244
void vtkImplicitModeller::SetSampleDimensions(int i, int j, int k)
Will Schroeder's avatar
Will Schroeder committed
245
246
247
248
249
250
251
252
253
254
{
  int dim[3];

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

  this->SetSampleDimensions(dim);
}

Ken Martin's avatar
Ken Martin committed
255
void vtkImplicitModeller::SetSampleDimensions(int dim[3])
Will Schroeder's avatar
Will Schroeder committed
256
{
Ken Martin's avatar
Ken Martin committed
257
  vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")");
Will Schroeder's avatar
Will Schroeder committed
258
259
260
261
262
263

  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
264
      vtkErrorMacro (<< "Bad Sample Dimensions, retaining previous values");
Will Schroeder's avatar
Will Schroeder committed
265
266
267
268
269
270
271
      return;
      }

    for (int dataDim=0, i=0; i<3 ; i++) if (dim[i] > 1) dataDim++;

    if ( dataDim  < 3 )
      {
Ken Martin's avatar
Ken Martin committed
272
      vtkErrorMacro(<<"Sample dimensions must define a volume!");
Will Schroeder's avatar
Will Schroeder committed
273
274
275
276
277
278
279
280
      return;
      }

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

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

Ken Martin's avatar
Ken Martin committed
282
void vtkImplicitModeller::Cap(vtkFloatScalars *s)
Will Schroeder's avatar
Will Schroeder committed
283
284
285
286
287
288
289
290
291
292
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
319
320
321
322
323
324
{
  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++)
      s->SetScalar(i+j*this->SampleDimensions[1], this->CapValue);

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

// 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
325
326
327
void vtkImplicitModeller::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToStructuredPointsFilter::PrintSelf(os,indent);
Will Schroeder's avatar
Will Schroeder committed
328

Will Schroeder's avatar
Will Schroeder committed
329
330
331
332
333
334
335
336
337
338
339
340
  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";
}