1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkSpheres.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 "vtkSpheres.h"
16 
17 #include "vtkDoubleArray.h"
18 #include "vtkObjectFactory.h"
19 #include "vtkPoints.h"
20 #include "vtkSphere.h"
21 
22 #include <cmath>
23 
24 vtkStandardNewMacro(vtkSpheres);
25 vtkCxxSetObjectMacro(vtkSpheres, Centers, vtkPoints);
26 
27 //------------------------------------------------------------------------------
vtkSpheres()28 vtkSpheres::vtkSpheres()
29 {
30   this->Centers = nullptr;
31   this->Radii = nullptr;
32   this->Sphere = vtkSphere::New();
33 }
34 
35 //------------------------------------------------------------------------------
~vtkSpheres()36 vtkSpheres::~vtkSpheres()
37 {
38   if (this->Centers)
39   {
40     this->Centers->UnRegister(this);
41   }
42   if (this->Radii)
43   {
44     this->Radii->UnRegister(this);
45   }
46   this->Sphere->Delete();
47 }
48 
49 //------------------------------------------------------------------------------
SetRadii(vtkDataArray * radii)50 void vtkSpheres::SetRadii(vtkDataArray* radii)
51 {
52   vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting Radii to " << radii);
53 
54   if (radii && radii->GetNumberOfComponents() != 1)
55   {
56     vtkWarningMacro("This array does not have 1 components. Ignoring radii.");
57     return;
58   }
59 
60   if (this->Radii != radii)
61   {
62     if (this->Radii != nullptr)
63     {
64       this->Radii->UnRegister(this);
65     }
66     this->Radii = radii;
67     if (this->Radii != nullptr)
68     {
69       this->Radii->Register(this);
70     }
71     this->Modified();
72   }
73 }
74 
75 //------------------------------------------------------------------------------
76 // Evaluate sphere equations. Return smallest absolute value.
EvaluateFunction(double x[3])77 double vtkSpheres::EvaluateFunction(double x[3])
78 {
79   int numSpheres, i;
80   double val, minVal;
81   double radius[1], center[3];
82 
83   if (!this->Centers || !this->Radii)
84   {
85     vtkErrorMacro(<< "Please define points and/or radii!");
86     return VTK_DOUBLE_MAX;
87   }
88 
89   if ((numSpheres = this->Centers->GetNumberOfPoints()) != this->Radii->GetNumberOfTuples())
90   {
91     vtkErrorMacro(<< "Number of radii/points inconsistent!");
92     return VTK_DOUBLE_MAX;
93   }
94 
95   for (minVal = VTK_DOUBLE_MAX, i = 0; i < numSpheres; i++)
96   {
97     this->Radii->GetTuple(i, radius);
98     this->Centers->GetPoint(i, center);
99     val = vtkSphere::Evaluate(center, radius[0], x);
100     if (val < minVal)
101     {
102       minVal = val;
103     }
104   }
105 
106   return minVal;
107 }
108 
109 //------------------------------------------------------------------------------
110 // Evaluate spheres gradient.
EvaluateGradient(double x[3],double n[3])111 void vtkSpheres::EvaluateGradient(double x[3], double n[3])
112 {
113   int numSpheres, i;
114   double val, minVal;
115   double rTemp[1];
116   double cTemp[3];
117 
118   if (!this->Centers || !this->Radii)
119   {
120     vtkErrorMacro(<< "Please define centers and radii!");
121     return;
122   }
123 
124   if ((numSpheres = this->Centers->GetNumberOfPoints()) != this->Radii->GetNumberOfTuples())
125   {
126     vtkErrorMacro(<< "Number of radii/centersinconsistent!");
127     return;
128   }
129 
130   for (minVal = VTK_DOUBLE_MAX, i = 0; i < numSpheres; i++)
131   {
132     this->Radii->GetTuple(i, rTemp);
133     this->Centers->GetPoint(i, cTemp);
134     val = vtkSphere::Evaluate(cTemp, rTemp[0], x);
135     if (val < minVal)
136     {
137       minVal = val;
138       n[0] = x[0] - cTemp[0];
139       n[1] = x[1] - cTemp[1];
140       n[2] = x[2] - cTemp[2];
141     }
142   }
143 }
144 
145 //------------------------------------------------------------------------------
GetNumberOfSpheres()146 int vtkSpheres::GetNumberOfSpheres()
147 {
148   if (this->Centers && this->Radii)
149   {
150     int npts = this->Centers->GetNumberOfPoints();
151     int nradii = this->Radii->GetNumberOfTuples();
152     return (npts <= nradii ? npts : nradii);
153   }
154   else
155   {
156     return 0;
157   }
158 }
159 
160 //------------------------------------------------------------------------------
GetSphere(int i)161 vtkSphere* vtkSpheres::GetSphere(int i)
162 {
163   double radius[1];
164   double center[3];
165 
166   if (i >= 0 && i < this->GetNumberOfSpheres())
167   {
168     this->Radii->GetTuple(i, radius);
169     this->Centers->GetPoint(i, center);
170     this->Sphere->SetRadius(radius[0]);
171     this->Sphere->SetCenter(center);
172     return this->Sphere;
173   }
174   else
175   {
176     return nullptr;
177   }
178 }
179 
180 //------------------------------------------------------------------------------
GetSphere(int i,vtkSphere * sphere)181 void vtkSpheres::GetSphere(int i, vtkSphere* sphere)
182 {
183   if (i >= 0 && i < this->GetNumberOfSpheres())
184   {
185     double radius[1];
186     double center[3];
187     this->Radii->GetTuple(i, radius);
188     this->Centers->GetPoint(i, center);
189     sphere->SetRadius(radius[0]);
190     sphere->SetCenter(center);
191   }
192 }
193 
194 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)195 void vtkSpheres::PrintSelf(ostream& os, vtkIndent indent)
196 {
197   this->Superclass::PrintSelf(os, indent);
198 
199   int numSpheres;
200   if (this->Centers && (numSpheres = this->Centers->GetNumberOfPoints()) > 0)
201   {
202     os << indent << "Number of Spheres: " << numSpheres << "\n";
203   }
204   else
205   {
206     os << indent << "No Spheres Defined.\n";
207   }
208 
209   if (this->Radii)
210   {
211     os << indent << "Radii: " << this->Radii << "\n";
212   }
213   else
214   {
215     os << indent << "Radii: (none)\n";
216   }
217 }
218