/*========================================================================= Program: Visualization Toolkit Module: vtkPlanes.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkPlanes.h" #include "vtkDoubleArray.h" #include "vtkObjectFactory.h" #include "vtkPlane.h" #include "vtkPoints.h" #include vtkStandardNewMacro(vtkPlanes); vtkCxxSetObjectMacro(vtkPlanes, Points, vtkPoints); //------------------------------------------------------------------------------ vtkPlanes::vtkPlanes() { int i; this->Points = nullptr; this->Normals = nullptr; this->Plane = vtkPlane::New(); for (i = 0; i < 24; i++) { this->Planes[i] = 0.0; } for (i = 0; i < 6; i++) { this->Bounds[i] = 0.0; } } //------------------------------------------------------------------------------ vtkPlanes::~vtkPlanes() { if (this->Points) { this->Points->UnRegister(this); } if (this->Normals) { this->Normals->UnRegister(this); } this->Plane->Delete(); } //------------------------------------------------------------------------------ void vtkPlanes::SetNormals(vtkDataArray* normals) { vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting Normals to " << normals); if (normals && normals->GetNumberOfComponents() != 3) { vtkWarningMacro("This array does not have 3 components. Ignoring normals."); return; } if (this->Normals != normals) { if (this->Normals != nullptr) { this->Normals->UnRegister(this); } this->Normals = normals; if (this->Normals != nullptr) { this->Normals->Register(this); } this->Modified(); } } //------------------------------------------------------------------------------ // Evaluate plane equations. Return the largest value. double vtkPlanes::EvaluateFunction(double x[3]) { int numPlanes, i; double val, maxVal; double normal[3], point[3]; if (!this->Points || !this->Normals) { vtkErrorMacro(<< "Please define points and/or normals!"); return VTK_DOUBLE_MAX; } if ((numPlanes = this->Points->GetNumberOfPoints()) != this->Normals->GetNumberOfTuples()) { vtkErrorMacro(<< "Number of normals/points inconsistent!"); return VTK_DOUBLE_MAX; } for (maxVal = -VTK_DOUBLE_MAX, i = 0; i < numPlanes; i++) { this->Normals->GetTuple(i, normal); this->Points->GetPoint(i, point); val = this->Plane->Evaluate(normal, point, x); if (val > maxVal) { maxVal = val; } } return maxVal; } //------------------------------------------------------------------------------ // Evaluate planes gradient. void vtkPlanes::EvaluateGradient(double x[3], double n[3]) { int numPlanes, i; double val, maxVal; double nTemp[3]; double pTemp[3]; if (!this->Points || !this->Normals) { vtkErrorMacro(<< "Please define points and/or normals!"); return; } if ((numPlanes = this->Points->GetNumberOfPoints()) != this->Normals->GetNumberOfTuples()) { vtkErrorMacro(<< "Number of normals/points inconsistent!"); return; } for (maxVal = -VTK_DOUBLE_MAX, i = 0; i < numPlanes; i++) { this->Normals->GetTuple(i, nTemp); this->Points->GetPoint(i, pTemp); val = this->Plane->Evaluate(nTemp, pTemp, x); if (val > maxVal) { maxVal = val; n[0] = nTemp[0]; n[1] = nTemp[1]; n[2] = nTemp[2]; } } } //------------------------------------------------------------------------------ void vtkPlanes::SetFrustumPlanes(double planes[24]) { int i; double *plane, n[3], x[3]; for (i = 0; i < 24; i++) { if (this->Planes[i] != planes[i]) { break; } } if (i >= 24) { return; // same as before don't modify } // okay, need to allocate stuff this->Modified(); vtkPoints* pts = vtkPoints::New(VTK_DOUBLE); vtkDoubleArray* normals = vtkDoubleArray::New(); pts->SetNumberOfPoints(6); normals->SetNumberOfComponents(3); normals->SetNumberOfTuples(6); this->SetPoints(pts); this->SetNormals(normals); for (i = 0; i < 6; i++) { plane = planes + 4 * i; n[0] = -plane[0]; n[1] = -plane[1]; n[2] = -plane[2]; x[0] = x[1] = x[2] = 0.0; if (n[0] != 0.0) { x[0] = plane[3] / n[0]; } else if (n[1] != 0.0) { x[1] = plane[3] / n[1]; } else { x[2] = plane[3] / n[2]; } pts->SetPoint(i, x); normals->SetTuple(i, n); } pts->Delete(); // ok reference counting normals->Delete(); } //------------------------------------------------------------------------------ void vtkPlanes::SetBounds(const double bounds[6]) { int i; double n[3], x[3]; for (i = 0; i < 6; i++) { if (this->Bounds[i] != bounds[i]) { break; } } if (i >= 6) { return; // same as before don't modify } // okay, need to allocate stuff this->Modified(); vtkPoints* pts = vtkPoints::New(); vtkDoubleArray* normals = vtkDoubleArray::New(); pts->SetNumberOfPoints(6); normals->SetNumberOfComponents(3); normals->SetNumberOfTuples(6); this->SetPoints(pts); this->SetNormals(normals); // Define the six planes // The x planes n[0] = -1.0; n[1] = 0.0; n[2] = 0.0; x[0] = this->Bounds[0] = bounds[0]; x[1] = 0.0; x[2] = 0.0; pts->SetPoint(0, x); normals->SetTuple(0, n); n[0] = 1.0; x[0] = this->Bounds[1] = bounds[1]; pts->SetPoint(1, x); normals->SetTuple(1, n); // The y planes n[0] = 0.0; n[1] = -1.0; n[2] = 0.0; x[0] = 0.0; x[1] = this->Bounds[2] = bounds[2]; x[2] = 0.0; pts->SetPoint(2, x); normals->SetTuple(2, n); n[1] = 1.0; x[1] = this->Bounds[3] = bounds[3]; pts->SetPoint(3, x); normals->SetTuple(3, n); // The z planes n[0] = 0.0; n[1] = 0.0; n[2] = -1.0; x[0] = 0.0; x[1] = 0.0; x[2] = this->Bounds[4] = bounds[4]; pts->SetPoint(4, x); normals->SetTuple(4, n); n[2] = 1.0; x[2] = this->Bounds[5] = bounds[5]; pts->SetPoint(5, x); normals->SetTuple(5, n); pts->Delete(); // ok reference counting normals->Delete(); } //------------------------------------------------------------------------------ void vtkPlanes::SetBounds( double xmin, double xmax, double ymin, double ymax, double zmin, double zmax) { double bounds[6]; bounds[0] = xmin; bounds[1] = xmax; bounds[2] = ymin; bounds[3] = ymax; bounds[4] = zmin; bounds[5] = zmax; this->SetBounds(bounds); } //------------------------------------------------------------------------------ int vtkPlanes::GetNumberOfPlanes() { if (this->Points && this->Normals) { int npts = this->Points->GetNumberOfPoints(); int nnormals = this->Normals->GetNumberOfTuples(); return (npts <= nnormals ? npts : nnormals); } else { return 0; } } //------------------------------------------------------------------------------ vtkPlane* vtkPlanes::GetPlane(int i) { double normal[3]; double point[3]; if (i >= 0 && i < this->GetNumberOfPlanes()) { this->Normals->GetTuple(i, normal); this->Points->GetPoint(i, point); this->Plane->SetNormal(normal); this->Plane->SetOrigin(point); return this->Plane; } else { return nullptr; } } //------------------------------------------------------------------------------ void vtkPlanes::GetPlane(int i, vtkPlane* plane) { if (i >= 0 && i < this->GetNumberOfPlanes()) { double normal[3]; double point[3]; this->Normals->GetTuple(i, normal); this->Points->GetPoint(i, point); plane->SetNormal(normal); plane->SetOrigin(point); } } //------------------------------------------------------------------------------ void vtkPlanes::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); int numPlanes; if (this->Points && (numPlanes = this->Points->GetNumberOfPoints()) > 0) { os << indent << "Number of Planes: " << numPlanes << "\n"; } else { os << indent << "No Planes Defined.\n"; } if (this->Normals) { os << indent << "Normals: " << this->Normals << "\n"; } else { os << indent << "Normals: (none)\n"; } }