// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkRectangularButtonSource.h" #include "vtkCellArray.h" #include "vtkFloatArray.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkPoints.h" #include "vtkPolyData.h" #include "vtkTransform.h" VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkRectangularButtonSource); //------------------------------------------------------------------------------ // Construct vtkRectangularButtonSource::vtkRectangularButtonSource() { this->Width = 0.5; this->Height = 0.5; this->Depth = 0.05; this->BoxRatio = 1.1; this->TextureRatio = 0.9; this->TextureHeightRatio = 0.95; this->OutputPointsPrecision = vtkAlgorithm::SINGLE_PRECISION; } //------------------------------------------------------------------------------ // One half of the button is made up of nine (quad) polygons. // static vtkIdType vtkRButtonPolys[72] = { 0, 1, 5, 4, // 1, 2, 6, 5, // 2, 3, 7, 6, // 3, 0, 4, 7, // 4, 5, 9, 8, // 5, 6, 10, 9, // 6, 7, 11, 10, // 7, 4, 8, 11, // 12, 13, 14, 15, // 1, 0, 16, 17, // 2, 1, 17, 18, // 3, 2, 18, 19, // 0, 3, 19, 16, // 17, 16, 20, 21, // 18, 17, 21, 22, // 19, 18, 22, 23, // 16, 19, 23, 20, // 25, 24, 27, 26 // }; //------------------------------------------------------------------------------ // Generate the button. // int vtkRectangularButtonSource::RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector) { vtkInformation* outInfo = outputVector->GetInformationObject(0); int i; vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); vtkDebugMacro(<< "Generating rectangular button"); // Check input if (this->Width <= 0.0 || this->Height <= 0.0) { vtkErrorMacro(<< "Button must have non-zero height and width"); return 1; } // Create the button in several steps. First, create the button in // the x-y plane. After this, the z-depth is created. And if // it is a two-sided button, then a mirror reflection of the button // in the negative z-direction is created. int numPts = 16; int numCells = 9; if (this->TwoSided) { numPts = 28; numCells *= 2; } // Allocate memory for everything vtkPoints* newPts = vtkPoints::New(); // Set the desired precision for the points in the output. if (this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION) { newPts->SetDataType(VTK_DOUBLE); } else { newPts->SetDataType(VTK_FLOAT); } newPts->SetNumberOfPoints(numPts); vtkFloatArray* tcoords = vtkFloatArray::New(); tcoords->SetNumberOfComponents(2); tcoords->SetNumberOfTuples(numPts); vtkCellArray* newPolys = vtkCellArray::New(); newPolys->AllocateEstimate(numCells, 1); // Generate the points and texture coordinates----------------------------- // double shoulderX = this->Width / 2.0; double boxX = this->BoxRatio * shoulderX; double textureX = this->TextureRatio * shoulderX; // may be adjusted later double shoulderY = this->Height / 2.0; double boxY = this->BoxRatio * shoulderY; double textureY = this->TextureRatio * shoulderY; // may be adjusted later double shoulderZ = this->Depth; double boxZ = 0.0; double textureZ = this->TextureHeightRatio * this->Depth; // Adjust the texture region if the texture region should be fit to the image if (this->TextureStyle == VTK_TEXTURE_STYLE_FIT_IMAGE) { double dX = (double)this->TextureDimensions[0]; double dY = (double)this->TextureDimensions[1]; double f1 = textureX / dX; double f2 = textureY / dY; if (f1 < f2) { textureX = f1 * dX; textureY = f1 * dY; } else { textureX = f2 * dX; textureY = f2 * dY; } } // The first four points are around the base newPts->SetPoint(0, this->Center[0] - boxX, this->Center[1] - boxY, this->Center[2] + boxZ); newPts->SetPoint(1, this->Center[0] + boxX, this->Center[1] - boxY, this->Center[2] + boxZ); newPts->SetPoint(2, this->Center[0] + boxX, this->Center[1] + boxY, this->Center[2] + boxZ); newPts->SetPoint(3, this->Center[0] - boxX, this->Center[1] + boxY, this->Center[2] + boxZ); // The next four points are around the shoulder newPts->SetPoint( 4, this->Center[0] - shoulderX, this->Center[1] - shoulderY, this->Center[2] + shoulderZ); newPts->SetPoint( 5, this->Center[0] + shoulderX, this->Center[1] - shoulderY, this->Center[2] + shoulderZ); newPts->SetPoint( 6, this->Center[0] + shoulderX, this->Center[1] + shoulderY, this->Center[2] + shoulderZ); newPts->SetPoint( 7, this->Center[0] - shoulderX, this->Center[1] + shoulderY, this->Center[2] + shoulderZ); // The next four points are between the shoulder and texture region newPts->SetPoint( 8, this->Center[0] - textureX, this->Center[1] - textureY, this->Center[2] + textureZ); newPts->SetPoint( 9, this->Center[0] + textureX, this->Center[1] - textureY, this->Center[2] + textureZ); newPts->SetPoint( 10, this->Center[0] + textureX, this->Center[1] + textureY, this->Center[2] + textureZ); newPts->SetPoint( 11, this->Center[0] - textureX, this->Center[1] + textureY, this->Center[2] + textureZ); // The last four points define the texture region newPts->SetPoint( 12, this->Center[0] - textureX, this->Center[1] - textureY, this->Center[2] + textureZ); newPts->SetPoint( 13, this->Center[0] + textureX, this->Center[1] - textureY, this->Center[2] + textureZ); newPts->SetPoint( 14, this->Center[0] + textureX, this->Center[1] + textureY, this->Center[2] + textureZ); newPts->SetPoint( 15, this->Center[0] - textureX, this->Center[1] + textureY, this->Center[2] + textureZ); if (this->TwoSided) { // The next four points are around the shoulder newPts->SetPoint( 16, this->Center[0] - shoulderX, this->Center[1] - shoulderY, this->Center[2] - shoulderZ); newPts->SetPoint( 17, this->Center[0] + shoulderX, this->Center[1] - shoulderY, this->Center[2] - shoulderZ); newPts->SetPoint( 18, this->Center[0] + shoulderX, this->Center[1] + shoulderY, this->Center[2] - shoulderZ); newPts->SetPoint( 19, this->Center[0] - shoulderX, this->Center[1] + shoulderY, this->Center[2] - shoulderZ); // The next four points are between the shoulder and texture region newPts->SetPoint( 20, this->Center[0] - textureX, this->Center[1] - textureY, this->Center[2] - textureZ); newPts->SetPoint( 21, this->Center[0] + textureX, this->Center[1] - textureY, this->Center[2] - textureZ); newPts->SetPoint( 22, this->Center[0] + textureX, this->Center[1] + textureY, this->Center[2] - textureZ); newPts->SetPoint( 23, this->Center[0] - textureX, this->Center[1] + textureY, this->Center[2] - textureZ); // The last four points define the texture region newPts->SetPoint( 24, this->Center[0] - textureX, this->Center[1] - textureY, this->Center[2] - textureZ); newPts->SetPoint( 25, this->Center[0] + textureX, this->Center[1] - textureY, this->Center[2] - textureZ); newPts->SetPoint( 26, this->Center[0] + textureX, this->Center[1] + textureY, this->Center[2] - textureZ); newPts->SetPoint( 27, this->Center[0] - textureX, this->Center[1] + textureY, this->Center[2] - textureZ); } // Generate the texture coordinates----------------------------- // // The shoulder has the same value. for (i = 0; i < 12; i++) { tcoords->SetTuple(i, this->ShoulderTextureCoordinate); } // The texture region has just the four points tcoords->SetTuple2(12, 0.0, 0.0); tcoords->SetTuple2(13, 1.0, 0.0); tcoords->SetTuple2(14, 1.0, 1.0); tcoords->SetTuple2(15, 0.0, 1.0); if (this->TwoSided) { for (i = 16; i < 24; i++) { tcoords->SetTuple(i, this->ShoulderTextureCoordinate); } // The texture region has just the four points tcoords->SetTuple2(24, 1.0, 0.0); tcoords->SetTuple2(25, 0.0, 0.0); tcoords->SetTuple2(26, 0.0, 1.0); tcoords->SetTuple2(27, 1.0, 1.0); } // Create the polygons------------------------------------------------------ // vtkIdType* buttonPtr = vtkRButtonPolys; for (i = 0; i < 9; i++, buttonPtr += 4) { newPolys->InsertNextCell(4, buttonPtr); } // If two sided, create the opposite side. // Make sure that faces ordering is reversed. if (this->TwoSided) { for (i = 0; i < 9; i++, buttonPtr += 4) { newPolys->InsertNextCell(4, buttonPtr); } } // Clean up and get out output->SetPoints(newPts); output->GetPointData()->SetTCoords(tcoords); output->SetPolys(newPolys); newPts->Delete(); tcoords->Delete(); newPolys->Delete(); return 1; } //------------------------------------------------------------------------------ void vtkRectangularButtonSource::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Width: " << this->Width << "\n"; os << indent << "Height: " << this->Height << "\n"; os << indent << "Depth: " << this->Depth << "\n"; os << indent << "BoxRatio: " << this->BoxRatio << "\n"; os << indent << "TextureRatio: " << this->TextureRatio << "\n"; os << indent << "TextureHeightRatio: " << this->TextureHeightRatio << "\n"; os << indent << "Output Points Precision: " << this->OutputPointsPrecision << "\n"; } VTK_ABI_NAMESPACE_END