// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkArcSource.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 "vtkStreamingDemandDrivenPipeline.h" #include VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkArcSource); //------------------------------------------------------------------------------ vtkArcSource::vtkArcSource(int res) { // Default first point this->Point1[0] = 0.0; this->Point1[1] = 0.5; this->Point1[2] = 0.0; // Default second point this->Point2[0] = 0.5; this->Point2[1] = 0.0; this->Point2[2] = 0.0; // Default center is origin this->Center[0] = 0.0; this->Center[1] = 0.0; this->Center[2] = 0.0; // Default normal vector is unit in the positive Z direction. this->Normal[0] = 0.0; this->Normal[1] = 0.0; this->Normal[2] = 1.0; // Default polar vector is unit in the positive X direction. this->PolarVector[0] = 1.0; this->PolarVector[1] = 0.0; this->PolarVector[2] = 0.0; // Default arc is a quarter-circle this->Angle = 90.; // Ensure resolution (number of line segments to approximate the arc) // is at least 1 this->Resolution = (res < 1 ? 1 : res); // By default use the shortest angular sector // rather than its complement (a.k.a. negative coterminal) this->Negative = false; // By default use the original API (endpoints + center) this->UseNormalAndAngle = false; this->OutputPointsPrecision = SINGLE_PRECISION; // This is a source this->SetNumberOfInputPorts(0); } //------------------------------------------------------------------------------ int vtkArcSource::RequestInformation(vtkInformation* vtkNotUsed(request), vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector) { // get the info object vtkInformation* outInfo = outputVector->GetInformationObject(0); outInfo->Set(CAN_HANDLE_PIECE_REQUEST(), 1); return 1; } //------------------------------------------------------------------------------ int vtkArcSource::RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector) { int numLines = this->Resolution; int numPts = this->Resolution + 1; double tc[3] = { 0.0, 0.0, 0.0 }; // get the info object vtkInformation* outInfo = outputVector->GetInformationObject(0); if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0) { return 1; } // get the output vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); // Calculate vector from origin to first point // Normal and angle are either specified (consistent API) or calculated (original API) double angle = 0.0; double radius = 0.5; double perpendicular[3]; double v1[3]; if (this->UseNormalAndAngle) { // Retrieve angle, which is specified with this API angle = vtkMath::RadiansFromDegrees(this->Angle); // Retrieve polar vector, which is specified with this API for (int i = 0; i < 3; ++i) { v1[i] = this->PolarVector[i]; } // Calculate perpendicular vector with normal which is specified with this API vtkMath::Cross(this->Normal, this->PolarVector, perpendicular); // Calculate radius radius = vtkMath::Normalize(v1); } else // if ( this->UseNormalAndAngle ) { // Compute the cross product of the two vectors. for (int i = 0; i < 3; ++i) { v1[i] = this->Point1[i] - this->Center[i]; } double v2[3] = { this->Point2[0] - this->Center[0], this->Point2[1] - this->Center[1], this->Point2[2] - this->Center[2] }; double normal[3]; vtkMath::Cross(v1, v2, normal); vtkMath::Cross(normal, v1, perpendicular); double dotprod = vtkMath::Dot(v1, v2) / (vtkMath::Norm(v1) * vtkMath::Norm(v2)); angle = acos(dotprod); if (this->Negative) { angle -= (2.0 * vtkMath::Pi()); } // Calcute radius radius = vtkMath::Normalize(v1); } // else // Calcute angle increment double angleInc = angle / this->Resolution; // Normalize perpendicular vector vtkMath::Normalize(perpendicular); // Now create arc points and segments vtkPoints* newPoints = vtkPoints::New(); // Set the desired precision for the points in the output. if (this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION) { newPoints->SetDataType(VTK_DOUBLE); } else { newPoints->SetDataType(VTK_FLOAT); } newPoints->Allocate(numPts); vtkFloatArray* newTCoords = vtkFloatArray::New(); newTCoords->SetNumberOfComponents(2); newTCoords->Allocate(2 * numPts); newTCoords->SetName("Texture Coordinates"); vtkCellArray* newLines = vtkCellArray::New(); newLines->AllocateEstimate(numLines, 2); double theta = 0.0; // Iterate over angle increments for (int i = 0; i <= this->Resolution; ++i, theta += angleInc) { const double cosine = cos(theta); const double sine = sin(theta); double p[3] = { this->Center[0] + cosine * radius * v1[0] + sine * radius * perpendicular[0], this->Center[1] + cosine * radius * v1[1] + sine * radius * perpendicular[1], this->Center[2] + cosine * radius * v1[2] + sine * radius * perpendicular[2] }; tc[0] = static_cast(i) / this->Resolution; newPoints->InsertPoint(i, p); newTCoords->InsertTuple(i, tc); } newLines->InsertNextCell(numPts); for (int k = 0; k < numPts; ++k) { newLines->InsertCellPoint(k); } output->SetPoints(newPoints); newPoints->Delete(); output->GetPointData()->SetTCoords(newTCoords); newTCoords->Delete(); output->SetLines(newLines); newLines->Delete(); return 1; } //------------------------------------------------------------------------------ void vtkArcSource::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Resolution: " << this->Resolution << "\n"; os << indent << "Point 1: (" << this->Point1[0] << ", " << this->Point1[1] << ", " << this->Point1[2] << ")\n"; os << indent << "Point 2: (" << this->Point2[0] << ", " << this->Point2[1] << ", " << this->Point2[2] << ")\n"; os << indent << "Center: (" << this->Center[0] << ", " << this->Center[1] << ", " << this->Center[2] << ")\n"; os << indent << "Normal: (" << this->Normal[0] << ", " << this->Normal[1] << ", " << this->Normal[2] << ")\n"; os << indent << "PolarVector: (" << this->PolarVector[0] << ", " << this->PolarVector[1] << ", " << this->PolarVector[2] << ")\n"; os << indent << "Angle: " << this->Angle << "\n"; os << indent << "Negative: " << this->Negative << "\n"; os << indent << "UseNormalAndAngle: " << this->UseNormalAndAngle << "\n"; os << indent << "Output Points Precision: " << this->OutputPointsPrecision << "\n"; } VTK_ABI_NAMESPACE_END