1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkPlanes.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 "vtkPlanes.h"
16
17 #include "vtkDoubleArray.h"
18 #include "vtkObjectFactory.h"
19 #include "vtkPlane.h"
20 #include "vtkPoints.h"
21
22 #include <cmath>
23
24 vtkStandardNewMacro(vtkPlanes);
25 vtkCxxSetObjectMacro(vtkPlanes,Points,vtkPoints);
26
27 //----------------------------------------------------------------------------
vtkPlanes()28 vtkPlanes::vtkPlanes()
29 {
30 int i;
31
32 this->Points = nullptr;
33 this->Normals = nullptr;
34 this->Plane = vtkPlane::New();
35
36 for (i=0; i<24; i++)
37 {
38 this->Planes[i] = 0.0;
39 }
40 for (i=0; i<6; i++)
41 {
42 this->Bounds[i] = 0.0;
43 }
44 }
45
46 //----------------------------------------------------------------------------
~vtkPlanes()47 vtkPlanes::~vtkPlanes()
48 {
49 if ( this->Points )
50 {
51 this->Points->UnRegister(this);
52 }
53 if ( this->Normals )
54 {
55 this->Normals->UnRegister(this);
56 }
57 this->Plane->Delete();
58 }
59
60 //----------------------------------------------------------------------------
SetNormals(vtkDataArray * normals)61 void vtkPlanes::SetNormals(vtkDataArray* normals)
62 {
63 vtkDebugMacro(<< this->GetClassName() << " (" << this
64 << "): setting Normals to " << normals );
65
66 if (normals && normals->GetNumberOfComponents() != 3)
67 {
68 vtkWarningMacro("This array does not have 3 components. Ignoring normals.");
69 return;
70 }
71
72 if (this->Normals != normals)
73 {
74 if (this->Normals != nullptr) { this->Normals->UnRegister(this); }
75 this->Normals = normals;
76 if (this->Normals != nullptr) { this->Normals->Register(this); }
77 this->Modified();
78 }
79 }
80
81 //----------------------------------------------------------------------------
82 // Evaluate plane equations. Return the largest value.
EvaluateFunction(double x[3])83 double vtkPlanes::EvaluateFunction(double x[3])
84 {
85 int numPlanes, i;
86 double val, maxVal;
87 double normal[3], point[3];
88
89 if ( !this->Points || ! this->Normals )
90 {
91 vtkErrorMacro(<<"Please define points and/or normals!");
92 return VTK_DOUBLE_MAX;
93 }
94
95 if ( (numPlanes=this->Points->GetNumberOfPoints()) != this->Normals->GetNumberOfTuples() )
96 {
97 vtkErrorMacro(<<"Number of normals/points inconsistent!");
98 return VTK_DOUBLE_MAX;
99 }
100
101 for (maxVal=-VTK_DOUBLE_MAX, i=0; i < numPlanes; i++)
102 {
103 this->Normals->GetTuple(i,normal);
104 this->Points->GetPoint(i,point);
105 val = this->Plane->Evaluate(normal, point, x);
106 if (val > maxVal )
107 {
108 maxVal = val;
109 }
110 }
111
112 return maxVal;
113 }
114
115 //----------------------------------------------------------------------------
116 // Evaluate planes gradient.
EvaluateGradient(double x[3],double n[3])117 void vtkPlanes::EvaluateGradient(double x[3], double n[3])
118 {
119 int numPlanes, i;
120 double val, maxVal;
121 double nTemp[3];
122 double pTemp[3];
123
124 if ( !this->Points || ! this->Normals )
125 {
126 vtkErrorMacro(<<"Please define points and/or normals!");
127 return;
128 }
129
130 if ( (numPlanes=this->Points->GetNumberOfPoints()) !=
131 this->Normals->GetNumberOfTuples() )
132 {
133 vtkErrorMacro(<<"Number of normals/points inconsistent!");
134 return;
135 }
136
137 for (maxVal=-VTK_DOUBLE_MAX, i=0; i < numPlanes; i++)
138 {
139 this->Normals->GetTuple(i, nTemp);
140 this->Points->GetPoint(i, pTemp);
141 val = this->Plane->Evaluate(nTemp, pTemp, x);
142 if ( val > maxVal )
143 {
144 maxVal = val;
145 n[0] = nTemp[0];
146 n[1] = nTemp[1];
147 n[2] = nTemp[2];
148 }
149 }
150 }
151
152 //----------------------------------------------------------------------------
SetFrustumPlanes(double planes[24])153 void vtkPlanes::SetFrustumPlanes(double planes[24])
154 {
155 int i;
156 double *plane, n[3], x[3];
157
158 for (i=0; i<24; i++)
159 {
160 if ( this->Planes[i] != planes[i] )
161 {
162 break;
163 }
164 }
165 if ( i >= 24 )
166 {
167 return; //same as before don't modify
168 }
169
170 // okay, need to allocate stuff
171 this->Modified();
172 vtkPoints *pts = vtkPoints::New();
173 vtkDoubleArray *normals = vtkDoubleArray::New();
174
175 pts->SetNumberOfPoints(6);
176 normals->SetNumberOfComponents(3);
177 normals->SetNumberOfTuples(6);
178 this->SetPoints(pts);
179 this->SetNormals(normals);
180
181 for (i=0; i<6; i++)
182 {
183 plane = planes + 4*i;
184 n[0] = -plane[0];
185 n[1] = -plane[1];
186 n[2] = -plane[2];
187 x[0] = x[1] = x[2] = 0.0;
188 if ( n[0] != 0.0 )
189 {
190 x[0] = plane[3] / n[0];
191 }
192 else if ( n[1] != 0.0 )
193 {
194 x[1] = plane[3] / n[1];
195 }
196 else
197 {
198 x[2] = plane[3] / n[2];
199 }
200 pts->SetPoint(i,x);
201 normals->SetTuple(i,n);
202 }
203
204 pts->Delete(); //ok reference counting
205 normals->Delete();
206 }
207
208 //----------------------------------------------------------------------------
SetBounds(const double bounds[6])209 void vtkPlanes::SetBounds(const double bounds[6])
210 {
211 int i;
212 double n[3], x[3];
213
214 for (i=0; i<6; i++)
215 {
216 if ( this->Bounds[i] != bounds[i] )
217 {
218 break;
219 }
220 }
221 if ( i >= 6 )
222 {
223 return; //same as before don't modify
224 }
225
226 // okay, need to allocate stuff
227 this->Modified();
228 vtkPoints *pts = vtkPoints::New();
229 vtkDoubleArray *normals = vtkDoubleArray::New();
230
231 pts->SetNumberOfPoints(6);
232 normals->SetNumberOfComponents(3);
233 normals->SetNumberOfTuples(6);
234 this->SetPoints(pts);
235 this->SetNormals(normals);
236
237 // Define the six planes
238 // The x planes
239 n[0] = -1.0;
240 n[1] = 0.0;
241 n[2] = 0.0;
242 x[0] = this->Bounds[0] = bounds[0];
243 x[1] = 0.0;
244 x[2] = 0.0;
245 pts->SetPoint(0,x);
246 normals->SetTuple(0,n);
247
248 n[0] = 1.0;
249 x[0] = this->Bounds[1] = bounds[1];
250 pts->SetPoint(1,x);
251 normals->SetTuple(1,n);
252
253 // The y planes
254 n[0] = 0.0;
255 n[1] = -1.0;
256 n[2] = 0.0;
257 x[0] = 0.0;
258 x[1] = this->Bounds[2] = bounds[2];
259 x[2] = 0.0;
260 pts->SetPoint(2,x);
261 normals->SetTuple(2,n);
262
263 n[1] = 1.0;
264 x[1] = this->Bounds[3] = bounds[3];
265 pts->SetPoint(3,x);
266 normals->SetTuple(3,n);
267
268 // The z planes
269 n[0] = 0.0;
270 n[1] = 0.0;
271 n[2] = -1.0;
272 x[0] = 0.0;
273 x[1] = 0.0;
274 x[2] = this->Bounds[4] = bounds[4];
275 pts->SetPoint(4,x);
276 normals->SetTuple(4,n);
277
278 n[2] = 1.0;
279 x[2] = this->Bounds[5] = bounds[5];
280 pts->SetPoint(5,x);
281 normals->SetTuple(5,n);
282
283 pts->Delete(); //ok reference counting
284 normals->Delete();
285 }
286
287 //----------------------------------------------------------------------------
SetBounds(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax)288 void vtkPlanes::SetBounds(double xmin, double xmax, double ymin, double ymax,
289 double zmin, double zmax)
290 {
291 double bounds[6];
292 bounds[0] = xmin;
293 bounds[1] = xmax;
294 bounds[2] = ymin;
295 bounds[3] = ymax;
296 bounds[4] = zmin;
297 bounds[5] = zmax;
298
299 this->SetBounds(bounds);
300 }
301
302 //----------------------------------------------------------------------------
GetNumberOfPlanes()303 int vtkPlanes::GetNumberOfPlanes()
304 {
305 if ( this->Points && this->Normals )
306 {
307 int npts = this->Points->GetNumberOfPoints();
308 int nnormals = this->Normals->GetNumberOfTuples();
309 return ( npts <= nnormals ? npts : nnormals );
310 }
311 else
312 {
313 return 0;
314 }
315 }
316
317 //----------------------------------------------------------------------------
GetPlane(int i)318 vtkPlane *vtkPlanes::GetPlane(int i)
319 {
320 double normal[3];
321 double point[3];
322
323 if ( i >= 0 && i < this->GetNumberOfPlanes() )
324 {
325 this->Normals->GetTuple(i,normal);
326 this->Points->GetPoint(i,point);
327 this->Plane->SetNormal(normal);
328 this->Plane->SetOrigin(point);
329 return this->Plane;
330 }
331 else
332 {
333 return nullptr;
334 }
335 }
336
337 //----------------------------------------------------------------------------
GetPlane(int i,vtkPlane * plane)338 void vtkPlanes::GetPlane(int i, vtkPlane *plane)
339 {
340 if ( i >= 0 && i < this->GetNumberOfPlanes() )
341 {
342 double normal[3];
343 double point[3];
344 this->Normals->GetTuple(i,normal);
345 this->Points->GetPoint(i,point);
346 plane->SetNormal(normal);
347 plane->SetOrigin(point);
348 }
349 }
350
351 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)352 void vtkPlanes::PrintSelf(ostream& os, vtkIndent indent)
353 {
354 this->Superclass::PrintSelf(os,indent);
355
356 int numPlanes;
357
358 if ( this->Points && (numPlanes=this->Points->GetNumberOfPoints()) > 0 )
359 {
360 os << indent << "Number of Planes: " << numPlanes << "\n";
361 }
362 else
363 {
364 os << indent << "No Planes Defined.\n";
365 }
366
367 if ( this->Normals )
368 {
369 os << indent << "Normals: " << this->Normals << "\n";
370 }
371 else
372 {
373 os << indent << "Normals: (none)\n";
374 }
375 }
376