vtkAppendPoints.cxx 6.59 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkAppendPoints.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 "vtkAppendPoints.h"

#include "vtkDataSetAttributes.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"
#include "vtkStringArray.h"
#include "vtkTable.h"

28 29
#include <set>
#include <vector>
30 31 32 33 34 35

vtkStandardNewMacro(vtkAppendPoints);

//----------------------------------------------------------------------------
vtkAppendPoints::vtkAppendPoints()
{
36
  this->InputIdArrayName = nullptr;
37
  this->OutputPointsPrecision = vtkAlgorithm::DEFAULT_PRECISION;
38 39 40 41 42
}

//----------------------------------------------------------------------------
vtkAppendPoints::~vtkAppendPoints()
{
43
  this->SetInputIdArrayName(nullptr);
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
}

//----------------------------------------------------------------------------
// This method is much too long, and has to be broken up!
// Append data sets into single polygonal data set.
int vtkAppendPoints::RequestData(vtkInformation *vtkNotUsed(request),
                                   vtkInformationVector **inputVector,
                                   vtkInformationVector *outputVector)
{
  vtkInformation *outInfo = outputVector->GetInformationObject(0);
  vtkPolyData *output = vtkPolyData::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  // Find common array names.
  vtkIdType totalPoints = 0;
  int numInputs = this->GetNumberOfInputConnections(0);
  bool first = true;
61
  std::set<std::string> arrayNames;
62
  for (int idx = 0; idx < numInputs; ++idx)
63
  {
64 65 66 67
    vtkInformation* inInfo = inputVector[0]->GetInformationObject(idx);
    vtkPolyData* input = vtkPolyData::SafeDownCast(
      inInfo->Get(vtkDataObject::DATA_OBJECT()));
    if (input && input->GetNumberOfPoints() > 0)
68
    {
69 70
      totalPoints += input->GetNumberOfPoints();
      if (first)
71
      {
72 73
        int numArrays = input->GetPointData()->GetNumberOfArrays();
        for (int a = 0; a < numArrays; ++a)
74
        {
75 76
          arrayNames.insert(input->GetPointData()->GetAbstractArray(a)->GetName());
        }
77 78
        first = false;
      }
79
      else
80
      {
81 82
        std::set<std::string> toErase;
        std::set<std::string>::iterator it, itEnd;
83 84
        itEnd = arrayNames.end();
        for (it = arrayNames.begin(); it != itEnd; ++it)
85
        {
86
          if (!input->GetPointData()->GetAbstractArray(it->c_str()))
87
          {
88 89
            toErase.insert(*it);
          }
90
        }
91 92
        itEnd = toErase.end();
        for (it = toErase.begin(); it != itEnd; ++it)
93
        {
94 95 96 97
          arrayNames.erase(*it);
        }
      }
    }
98
  }
99

100
  std::vector<vtkSmartPointer<vtkPolyData> > inputs;
101
  for (int idx = 0; idx < numInputs; ++idx)
102
  {
103 104 105 106
    vtkInformation* inInfo = inputVector[0]->GetInformationObject(idx);
    vtkPolyData* input = vtkPolyData::SafeDownCast(
      inInfo->Get(vtkDataObject::DATA_OBJECT()));
    if (input && input->GetNumberOfPoints() > 0)
107
    {
108 109 110
      vtkSmartPointer<vtkPolyData> copy =
        vtkSmartPointer<vtkPolyData>::New();
      copy->SetPoints(input->GetPoints());
111
      std::set<std::string>::iterator it, itEnd;
112 113
      itEnd = arrayNames.end();
      for (it = arrayNames.begin(); it != itEnd; ++it)
114
      {
115 116 117
        copy->GetPointData()->AddArray(
          input->GetPointData()->GetAbstractArray(it->c_str()));
      }
118 119
      inputs.push_back(copy);
    }
120
    else
121
    {
122
      inputs.push_back(nullptr);
123
    }
124
  }
125

126
  vtkPointData* pd = nullptr;
127 128
  vtkIdType index = 0;
  vtkSmartPointer<vtkPoints> pts = vtkSmartPointer<vtkPoints>::New();
129 130 131

  // Set the desired precision for the points in the output.
  if(this->OutputPointsPrecision == vtkAlgorithm::DEFAULT_PRECISION)
132
  {
133 134 135
    // The points in distinct inputs may be of differing precisions.
    pts->SetDataType(VTK_FLOAT);
    for (size_t idx = 0; idx < inputs.size(); ++idx)
136
    {
137 138 139 140
      vtkPolyData* input = inputs[idx];

      // Set the desired precision to VTK_DOUBLE if the precision of the
      // points in any of the inputs is VTK_DOUBLE.
141
      if(input && input->GetPoints() && input->GetPoints()->GetDataType() == VTK_DOUBLE)
142
      {
143 144 145 146
        pts->SetDataType(VTK_DOUBLE);
        break;
      }
    }
147
  }
148
  else if(this->OutputPointsPrecision == vtkAlgorithm::SINGLE_PRECISION)
149
  {
150
    pts->SetDataType(VTK_FLOAT);
151
  }
152
  else if(this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION)
153
  {
154
    pts->SetDataType(VTK_DOUBLE);
155
  }
156

157 158 159
  pts->SetNumberOfPoints(totalPoints);
  vtkSmartPointer<vtkIntArray> idArr;
  if (this->InputIdArrayName)
160
  {
161 162 163
    idArr = vtkSmartPointer<vtkIntArray>::New();
    idArr->SetName(this->InputIdArrayName);
    idArr->SetNumberOfTuples(totalPoints);
164
  }
165
  for (size_t idx = 0; idx < inputs.size(); ++idx)
166
  {
167 168
    vtkPolyData* input = inputs[idx];
    if (input)
169
    {
170 171
      vtkPointData* ipd = input->GetPointData();
      if (!pd)
172
      {
173 174
        pd = output->GetPointData();
        pd->CopyAllocate(ipd, totalPoints);
175
      }
176 177
      vtkIdType numPoints = input->GetNumberOfPoints();
      for (vtkIdType i = 0; i < numPoints; ++i)
178
      {
179 180 181
        pd->CopyData(ipd, i, index);
        pts->InsertPoint(index, input->GetPoint(i));
        if (this->InputIdArrayName)
182
        {
183
          idArr->InsertValue(index, static_cast<int>(idx));
184
        }
185
        ++index;
186 187
      }
    }
188
  }
189 190
  output->SetPoints(pts);
  if (this->InputIdArrayName)
191
  {
192
    output->GetPointData()->AddArray(idArr);
193
  }
194 195 196 197 198 199 200 201 202

  return 1;
}

//----------------------------------------------------------------------------
void vtkAppendPoints::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  os << indent << "InputIdArrayName: "
203 204 205
     << (this->InputIdArrayName ? this->InputIdArrayName : "(none)") << endl
     << indent << "Output Points Precision: " << this->OutputPointsPrecision
     << endl;
206 207 208 209 210 211
}

//----------------------------------------------------------------------------
int vtkAppendPoints::FillInputPortInformation(int port, vtkInformation *info)
{
  if (!this->Superclass::FillInputPortInformation(port, info))
212
  {
213
    return 0;
214
  }
215 216 217 218
  info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
  info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
  return 1;
}