1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImplicitSum.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 "vtkImplicitSum.h"
16 
17 #include "vtkDoubleArray.h"
18 #include "vtkImplicitFunctionCollection.h"
19 #include "vtkObjectFactory.h"
20 
21 #include <cmath>
22 
23 vtkStandardNewMacro(vtkImplicitSum);
24 
25 //----------------------------------------------------------------------------
26 // Constructor.
vtkImplicitSum()27 vtkImplicitSum::vtkImplicitSum()
28 {
29   this->FunctionList = vtkImplicitFunctionCollection::New();
30   this->Weights = vtkDoubleArray::New();
31   this->Weights->SetNumberOfComponents(1);
32   this->TotalWeight = 0.0;
33   this->NormalizeByWeight = 0;
34 }
35 
36 //----------------------------------------------------------------------------
~vtkImplicitSum()37 vtkImplicitSum::~vtkImplicitSum()
38 {
39   this->FunctionList->Delete();
40   this->Weights->Delete();
41 }
42 
43 //----------------------------------------------------------------------------
GetMTime()44 vtkMTimeType vtkImplicitSum::GetMTime()
45 {
46   vtkMTimeType fMtime;
47   vtkMTimeType mtime = this->vtkImplicitFunction::GetMTime();
48   vtkImplicitFunction *f;
49 
50   fMtime = this->Weights->GetMTime();
51   if ( fMtime > mtime )
52   {
53     mtime = fMtime;
54   }
55 
56   vtkCollectionSimpleIterator sit;
57   for (this->FunctionList->InitTraversal(sit);
58        (f=this->FunctionList->GetNextImplicitFunction(sit)); )
59   {
60     fMtime = f->GetMTime();
61     if ( fMtime > mtime )
62     {
63       mtime = fMtime;
64     }
65   }
66   return mtime;
67 }
68 
69 //----------------------------------------------------------------------------
70 // Add another implicit function to the list of functions.
AddFunction(vtkImplicitFunction * f,double scale)71 void vtkImplicitSum::AddFunction(vtkImplicitFunction *f, double scale)
72 {
73   this->Modified();
74   this->FunctionList->AddItem(f);
75   this->Weights->InsertNextValue(scale);
76   this->CalculateTotalWeight();
77 }
78 
79 //----------------------------------------------------------------------------
SetFunctionWeight(vtkImplicitFunction * f,double scale)80 void vtkImplicitSum::SetFunctionWeight(vtkImplicitFunction *f, double scale)
81 {
82   int loc = this->FunctionList->IsItemPresent(f);
83   if (! loc)
84   {
85     vtkWarningMacro("Function not found in function list");
86     return;
87   }
88   loc--; // IsItemPresent returns index+1.
89 
90   if ( this->Weights->GetValue(loc) != scale )
91   {
92     this->Modified();
93     this->Weights->SetValue(loc, scale);
94     this->CalculateTotalWeight();
95   }
96 }
97 
98 //----------------------------------------------------------------------------
RemoveAllFunctions()99 void vtkImplicitSum::RemoveAllFunctions()
100 {
101   this->Modified();
102   this->FunctionList->RemoveAllItems();
103   this->Weights->Initialize();
104   this->TotalWeight = 0.0;
105 }
106 
107 //----------------------------------------------------------------------------
CalculateTotalWeight(void)108 void vtkImplicitSum::CalculateTotalWeight(void)
109 {
110   this->TotalWeight = 0.0;
111 
112   for(int i = 0; i < this->Weights->GetNumberOfTuples(); ++i)
113   {
114     this->TotalWeight += this->Weights->GetValue(i);
115   }
116 }
117 
118 
119 //----------------------------------------------------------------------------
120 // Evaluate sum of implicit functions.
EvaluateFunction(double x[3])121 double vtkImplicitSum::EvaluateFunction(double x[3])
122 {
123   double sum = 0;
124   double c;
125   int i;
126   vtkImplicitFunction *f;
127   double *weights = this->Weights->GetPointer(0);
128 
129   vtkCollectionSimpleIterator sit;
130   for (i = 0, this->FunctionList->InitTraversal(sit);
131        (f=this->FunctionList->GetNextImplicitFunction(sit)); i++)
132   {
133     c = weights[i];
134     if (c != 0.0)
135     {
136       sum += f->FunctionValue(x)*c;
137     }
138   }
139   if (this->NormalizeByWeight && this->TotalWeight != 0.0)
140   {
141     sum /= this->TotalWeight;
142   }
143   return sum;
144 }
145 
146 //----------------------------------------------------------------------------
147 // Evaluate gradient of sum of functions (valid only if linear)
EvaluateGradient(double x[3],double g[3])148 void vtkImplicitSum::EvaluateGradient(double x[3], double g[3])
149 {
150   double c;
151   int i;
152   double gtmp[3];
153   vtkImplicitFunction *f;
154   double *weights = this->Weights->GetPointer(0);
155 
156   g[0] = g[1] = g[2] = 0.0;
157   vtkCollectionSimpleIterator sit;
158   for (i = 0, this->FunctionList->InitTraversal(sit);
159        (f=this->FunctionList->GetNextImplicitFunction(sit)); i++)
160   {
161     c = weights[i];
162     if ( c != 0.0 )
163     {
164       f->FunctionGradient(x, gtmp);
165       g[0] += gtmp[0]*c;
166       g[1] += gtmp[1]*c;
167       g[2] += gtmp[2]*c;
168     }
169   }
170 
171   if (this->NormalizeByWeight && this->TotalWeight != 0.0)
172   {
173     g[0] /= this->TotalWeight;
174     g[1] /= this->TotalWeight;
175     g[2] /= this->TotalWeight;
176   }
177 }
178 
179 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)180 void vtkImplicitSum::PrintSelf(ostream& os, vtkIndent indent)
181 {
182   this->Superclass::PrintSelf(os,indent);
183 
184   os << indent << "NormalizeByWeight: "
185      << (this->NormalizeByWeight ? "On\n" : "Off\n");
186 
187   os << indent << "Function List:\n";
188   this->FunctionList->PrintSelf(os,indent.GetNextIndent());
189 
190   os << indent << "Weights:\n";
191   this->Weights->PrintSelf(os,indent.GetNextIndent());
192 }
193