/*========================================================================= Program: Visualization Toolkit Module: vtkImplicitBoolean.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 "vtkImplicitBoolean.h" #include "vtkImplicitFunctionCollection.h" #include "vtkObjectFactory.h" #include vtkStandardNewMacro(vtkImplicitBoolean); // Construct with union operation. vtkImplicitBoolean::vtkImplicitBoolean() { this->OperationType = VTK_UNION; this->FunctionList = vtkImplicitFunctionCollection::New(); } vtkImplicitBoolean::~vtkImplicitBoolean() { this->FunctionList->Delete(); } vtkMTimeType vtkImplicitBoolean::GetMTime() { vtkMTimeType fMtime; vtkMTimeType mtime = this->vtkImplicitFunction::GetMTime(); vtkImplicitFunction* f; vtkCollectionSimpleIterator sit; for (this->FunctionList->InitTraversal(sit); (f = this->FunctionList->GetNextImplicitFunction(sit));) { fMtime = f->GetMTime(); if (fMtime > mtime) { mtime = fMtime; } } return mtime; } // Add another implicit function to the list of functions. void vtkImplicitBoolean::AddFunction(vtkImplicitFunction* f) { if (!this->FunctionList->IsItemPresent(f)) { this->Modified(); this->FunctionList->AddItem(f); } } // Remove a function from the list of implicit functions to boolean. void vtkImplicitBoolean::RemoveFunction(vtkImplicitFunction* f) { if (this->FunctionList->IsItemPresent(f)) { this->Modified(); this->FunctionList->RemoveItem(f); } } // Evaluate boolean combinations of implicit function using current operator. double vtkImplicitBoolean::EvaluateFunction(double x[3]) { double value = 0; double v; vtkImplicitFunction* f; if (this->FunctionList->GetNumberOfItems() == 0) { return value; } vtkCollectionSimpleIterator sit; if (this->OperationType == VTK_UNION) { // take minimum value for (value = VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); (f = this->FunctionList->GetNextImplicitFunction(sit));) { if ((v = f->FunctionValue(x)) < value) { value = v; } } } else if (this->OperationType == VTK_INTERSECTION) { // take maximum value for (value = -VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); (f = this->FunctionList->GetNextImplicitFunction(sit));) { if ((v = f->FunctionValue(x)) > value) { value = v; } } } else if (this->OperationType == VTK_UNION_OF_MAGNITUDES) { // take minimum absolute value for (value = VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); (f = this->FunctionList->GetNextImplicitFunction(sit));) { if ((v = fabs(f->FunctionValue(x))) < value) { value = v; } } } else // difference { vtkImplicitFunction* firstF; this->FunctionList->InitTraversal(sit); if ((firstF = this->FunctionList->GetNextImplicitFunction(sit)) != nullptr) { value = firstF->FunctionValue(x); } for (this->FunctionList->InitTraversal(sit); (f = this->FunctionList->GetNextImplicitFunction(sit));) { if (f != firstF) { if ((v = (-1.0) * f->FunctionValue(x)) > value) { value = v; } } } } // else return value; } // Evaluate gradient of boolean combination. void vtkImplicitBoolean::EvaluateGradient(double x[3], double g[3]) { double value = 0; double v; vtkImplicitFunction* f; vtkCollectionSimpleIterator sit; if (this->FunctionList->GetNumberOfItems() == 0) { g[0] = 0; g[1] = 0; g[2] = 0; return; } if (this->OperationType == VTK_UNION) { // take minimum value for (value = VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); (f = this->FunctionList->GetNextImplicitFunction(sit));) { if ((v = f->FunctionValue(x)) < value) { value = v; f->FunctionGradient(x, g); } } } else if (this->OperationType == VTK_INTERSECTION) { // take maximum value for (value = -VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); (f = this->FunctionList->GetNextImplicitFunction(sit));) { if ((v = f->FunctionValue(x)) > value) { value = v; f->FunctionGradient(x, g); } } } if (this->OperationType == VTK_UNION_OF_MAGNITUDES) { // take minimum value for (value = VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); (f = this->FunctionList->GetNextImplicitFunction(sit));) { if ((v = fabs(f->FunctionValue(x))) < value) { value = v; f->FunctionGradient(x, g); } } } else // difference { double gTemp[3]; vtkImplicitFunction* firstF; this->FunctionList->InitTraversal(sit); if ((firstF = this->FunctionList->GetNextImplicitFunction(sit)) != nullptr) { value = firstF->FunctionValue(x); firstF->FunctionGradient(x, gTemp); g[0] = -1.0 * gTemp[0]; g[1] = -1.0 * gTemp[1]; g[2] = -1.0 * gTemp[2]; } for (this->FunctionList->InitTraversal(sit); (f = this->FunctionList->GetNextImplicitFunction(sit));) { if (f != firstF) { if ((v = (-1.0) * f->FunctionValue(x)) > value) { value = v; f->FunctionGradient(x, gTemp); g[0] = -1.0 * gTemp[0]; g[1] = -1.0 * gTemp[1]; g[2] = -1.0 * gTemp[2]; } } } } // else } void vtkImplicitBoolean::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Function List:\n"; this->FunctionList->PrintSelf(os, indent.GetNextIndent()); os << indent << "Operator Type: "; if (this->OperationType == VTK_INTERSECTION) { os << "VTK_INTERSECTION\n"; } else if (this->OperationType == VTK_UNION) { os << "VTK_UNION\n"; } else if (this->OperationType == VTK_UNION_OF_MAGNITUDES) { os << "VTK_UNION_OF_MAGNITUDES\n"; } else { os << "VTK_DIFFERENCE\n"; } }