text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    TestNamedComponents.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 "vtkArrayCalculator.h"
  #include "vtkCellData.h"
  #include "vtkIdTypeArray.h"
  #include "vtkIntArray.h"
  #include "vtkPointData.h"
  #include "vtkPoints.h"
  #include "vtkPolyData.h"
  #include "vtkSmartPointer.h"
  #include "vtkThreshold.h"
  #include "vtkUnstructuredGrid.h"
  
  int TestNamedComponents(int, char*[])
  {
    int rval = 0;
  
    vtkIdType numPoints = 20;
    vtkIdType numVerts = 5;
    vtkIdType numLines = 8;
    vtkIdType numTriangles = 3;
    vtkIdType numStrips = 2;
    vtkIdType numCells = numVerts + numLines + numTriangles + numStrips;
    vtkIdType i;
  
    vtkIdTypeArray* pointCoords = vtkIdTypeArray::New();
    const char pcName[] = "point coords";
    pointCoords->SetName(pcName);
    pointCoords->SetNumberOfComponents(3); // num points + point ids
    pointCoords->SetNumberOfTuples(numPoints);
    pointCoords->SetComponentName(0, "XLOC");
    pointCoords->SetComponentName(1, "YLOC");
    pointCoords->SetComponentName(2, "ZLOC");
  
    vtkPoints* points = vtkPoints::New();
    points->SetNumberOfPoints(numPoints);
    for (i = 0; i < numPoints; i++)
    {
      double loc[3] = { static_cast<double>(i), static_cast<double>(i * i), 0.0 };
      points->InsertPoint(i, loc);
      pointCoords->InsertTuple(i, loc);
    }
    vtkSmartPointer<vtkPolyData> poly = vtkSmartPointer<vtkPolyData>::New();
    poly->AllocateExact(numCells, numCells);
    poly->SetPoints(points);
    poly->GetPointData()->AddArray(pointCoords);
    pointCoords->Delete();
    points->Delete();
  
    for (i = 0; i < numVerts; i++)
    {
      poly->InsertNextCell(VTK_VERTEX, 1, &i);
    }
  
    for (i = 0; i < numLines; i++)
    {
      vtkIdType pts[2] = { i, i + 1 };
      poly->InsertNextCell(VTK_LINE, 2, pts);
    }
  
    for (i = 0; i < numTriangles; i++)
    {
      vtkIdType pts[3] = { 0, i + 1, i + 2 };
      poly->InsertNextCell(VTK_TRIANGLE, 3, pts);
    }
  
    for (i = 0; i < numStrips; i++)
    {
      vtkIdType pts[3] = { 0, i + 1, i + 2 };
      poly->InsertNextCell(VTK_TRIANGLE_STRIP, 3, pts);
    }
  
    vtkIntArray* cellIndex = vtkIntArray::New();
    const char ctName[] = "scalars";
    cellIndex->SetName(ctName);
    cellIndex->SetNumberOfComponents(1);
    cellIndex->SetNumberOfTuples(numCells);
    cellIndex->SetComponentName(0, "index");
    for (i = 0; i < numCells; i++)
    {
      cellIndex->SetValue(i, i);
    }
    poly->GetCellData()->SetScalars(cellIndex);
    cellIndex->Delete();
  
    vtkIdTypeArray* cellPoints = vtkIdTypeArray::New();
    const char cpName[] = "cell points";
    cellPoints->SetName(cpName);
    cellPoints->SetNumberOfComponents(4); // num points + point ids
    cellPoints->SetNumberOfTuples(numCells);
  
    cellPoints->SetComponentName(0, "NumberOfPoints");
    cellPoints->SetComponentName(1, "X_ID");
    cellPoints->SetComponentName(2, "Y_ID");
    cellPoints->SetComponentName(3, "Z_ID");
  
    for (i = 0; i < numCells; i++)
    {
      vtkIdType npts;
      const vtkIdType* pts;
      poly->GetCellPoints(i, npts, pts);
      vtkIdType data[4] = { npts, pts[0], 0, 0 };
      for (vtkIdType j = 1; j < npts; j++)
      {
        data[j + 1] = pts[j];
      }
      cellPoints->SetTypedTuple(i, data);
    }
  
    poly->GetCellData()->AddArray(cellPoints);
    cellPoints->Delete();
  
    poly->BuildCells();
  
    vtkSmartPointer<vtkThreshold> thresh = vtkSmartPointer<vtkThreshold>::New();
    thresh->SetInputData(poly);
    thresh->SetInputArrayToProcess(
      0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, vtkDataSetAttributes::SCALARS);
  
    thresh->ThresholdBetween(0, 10);
    thresh->Update();
  
    vtkSmartPointer<vtkUnstructuredGrid> out = thresh->GetOutput();
  
    if (out == nullptr)
    {
      vtkGenericWarningMacro("threshold failed.");
      return 1;
    }
  
    // the arrays should have been changed so get them again...
    cellIndex = vtkArrayDownCast<vtkIntArray>(out->GetCellData()->GetArray(ctName));
    cellPoints = vtkArrayDownCast<vtkIdTypeArray>(out->GetCellData()->GetArray(cpName));
  
    // confirm component names are intact
    if (strcmp(cellIndex->GetComponentName(0), "index") != 0)
    {
      vtkGenericWarningMacro("threshold failed to maintain component name on cell scalars.");
      return 1;
    }
  
    if (strcmp(cellPoints->GetComponentName(0), "NumberOfPoints") != 0 ||
      strcmp(cellPoints->GetComponentName(1), "X_ID") != 0 ||
      strcmp(cellPoints->GetComponentName(2), "Y_ID") != 0 ||
      strcmp(cellPoints->GetComponentName(3), "Z_ID") != 0)
    {
      vtkGenericWarningMacro("threshold failed to maintain component names on point property.");
      return 1;
    }
  
    // Test component names with the calculator
    vtkSmartPointer<vtkArrayCalculator> calc = vtkSmartPointer<vtkArrayCalculator>::New();
    calc->SetInputData(poly);
    calc->SetAttributeTypeToPointData();
    // Add coordinate scalar and vector variables
    calc->AddCoordinateScalarVariable("coordsX", 0);
    calc->AddScalarVariable("\"point coords_YLOC\"", "point coords", 1);
    calc->SetFunction("coordsX + \"point coords_YLOC\"");
    calc->SetResultArrayName("Result");
    calc->Update();
  
    return rval;
  }
  