PageRenderTime 54ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/Filters/General/vtkVolumeContourSpectrumFilter.cxx

http://github.com/Kitware/VTK
C++ | 305 lines | 215 code | 41 blank | 49 comment | 32 complexity | 3cd1e3997aedb96d1ea2021b6091a400 MD5 | raw file
Possible License(s): JSON, BSD-3-Clause, LGPL-2.0, LGPL-3.0, GPL-2.0, Apache-2.0
  1. /*=========================================================================
  2. Program: Visualization Toolkit
  3. Module: vtkVolumeContourSpectrumFilter.cxx
  4. Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  5. All rights reserved.
  6. See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  7. This software is distributed WITHOUT ANY WARRANTY; without even
  8. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  9. PURPOSE. See the above copyright notice for more information.
  10. =========================================================================*/
  11. #include "vtkVolumeContourSpectrumFilter.h"
  12. #include "vtkDataArray.h"
  13. #include "vtkDataSetAttributes.h"
  14. #include "vtkEdgeListIterator.h"
  15. #include "vtkIdList.h"
  16. #include "vtkInformation.h"
  17. #include "vtkInformationVector.h"
  18. #include "vtkObjectFactory.h"
  19. #include "vtkPointData.h"
  20. #include "vtkReebGraph.h"
  21. #include "vtkTable.h"
  22. #include "vtkTetra.h"
  23. #include "vtkUnstructuredGrid.h"
  24. #include "vtkVariantArray.h"
  25. vtkStandardNewMacro(vtkVolumeContourSpectrumFilter);
  26. //------------------------------------------------------------------------------
  27. vtkVolumeContourSpectrumFilter::vtkVolumeContourSpectrumFilter()
  28. {
  29. this->SetNumberOfInputPorts(2);
  30. this->ArcId = 0;
  31. this->FieldId = 0;
  32. this->NumberOfSamples = 100;
  33. }
  34. //------------------------------------------------------------------------------
  35. vtkVolumeContourSpectrumFilter::~vtkVolumeContourSpectrumFilter() = default;
  36. //------------------------------------------------------------------------------
  37. int vtkVolumeContourSpectrumFilter::FillInputPortInformation(int portNumber, vtkInformation* info)
  38. {
  39. switch (portNumber)
  40. {
  41. case 0:
  42. info->Remove(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE());
  43. info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid");
  44. break;
  45. case 1:
  46. info->Remove(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE());
  47. info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkReebGraph");
  48. break;
  49. }
  50. return 1;
  51. }
  52. //------------------------------------------------------------------------------
  53. int vtkVolumeContourSpectrumFilter::FillOutputPortInformation(
  54. int vtkNotUsed(portNumber), vtkInformation* info)
  55. {
  56. info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkTable");
  57. return 1;
  58. }
  59. //------------------------------------------------------------------------------
  60. void vtkVolumeContourSpectrumFilter::PrintSelf(ostream& os, vtkIndent indent)
  61. {
  62. this->Superclass::PrintSelf(os, indent);
  63. os << indent << "Arc Id: " << this->ArcId << "\n";
  64. os << indent << "Number of Samples: " << this->NumberOfSamples << "\n";
  65. os << indent << "Field Id: " << this->FieldId << "\n";
  66. }
  67. //------------------------------------------------------------------------------
  68. vtkTable* vtkVolumeContourSpectrumFilter::GetOutput()
  69. {
  70. return vtkTable::SafeDownCast(this->GetOutputDataObject(0));
  71. }
  72. //------------------------------------------------------------------------------
  73. int vtkVolumeContourSpectrumFilter::RequestData(vtkInformation* vtkNotUsed(request),
  74. vtkInformationVector** inputVector, vtkInformationVector* outputVector)
  75. {
  76. vtkInformation *inInfoMesh = inputVector[0]->GetInformationObject(0),
  77. *inInfoGraph = inputVector[1]->GetInformationObject(0);
  78. if ((!inInfoMesh) || (!inInfoGraph))
  79. {
  80. return 0;
  81. }
  82. vtkUnstructuredGrid* inputMesh =
  83. vtkUnstructuredGrid::SafeDownCast(inInfoMesh->Get(vtkUnstructuredGrid::DATA_OBJECT()));
  84. vtkReebGraph* inputGraph =
  85. vtkReebGraph::SafeDownCast(inInfoGraph->Get(vtkReebGraph::DATA_OBJECT()));
  86. if ((inputMesh) && (inputGraph))
  87. {
  88. vtkInformation* outInfo = outputVector->GetInformationObject(0);
  89. vtkTable* output = vtkTable::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
  90. if (output)
  91. {
  92. // Retrieve the arc given by ArcId
  93. vtkVariantArray* edgeInfo = vtkArrayDownCast<vtkVariantArray>(
  94. inputGraph->GetEdgeData()->GetAbstractArray("Vertex Ids"));
  95. // Invalid Reeb graph (no information associated to the edges)
  96. if (!edgeInfo)
  97. return 0;
  98. // Retrieve the information to get the critical vertices Ids
  99. vtkDataArray* criticalPointIds =
  100. vtkArrayDownCast<vtkDataArray>(inputGraph->GetVertexData()->GetAbstractArray("Vertex Ids"));
  101. // Invalid Reeb graph (no information associated to the vertices)
  102. if (!criticalPointIds)
  103. return 0;
  104. vtkAbstractArray* vertexList = edgeInfo->GetPointer(ArcId)->ToArray();
  105. // the arc defined by ArcId does not exist (out of bound?)
  106. if (!vertexList)
  107. return 0;
  108. vtkDataArray* scalarField = inputMesh->GetPointData()->GetArray(FieldId);
  109. if (!scalarField)
  110. return 0;
  111. // parse the input vertex list (region in which the connectivity of the
  112. // level sets does not change) and compute the area signature
  113. double cumulativeVolume = 0;
  114. std::vector<double> scalarValues, volumeSignature;
  115. std::vector<int> vertexIds;
  116. std::vector<bool> visitedTetrahedra;
  117. visitedTetrahedra.resize(inputMesh->GetNumberOfCells());
  118. vertexIds.resize(vertexList->GetNumberOfTuples() + 2);
  119. scalarValues.resize(vertexIds.size());
  120. volumeSignature.resize(vertexIds.size());
  121. // include the critical points in the computation
  122. // - iterates through the edges of the Reeb graph until we found the arc
  123. // we're looking for
  124. // - retrieve the Source and Target of the edge
  125. // - pick the corresponding mesh vertex Ids in the VertexData.
  126. std::pair<int, int> criticalPoints;
  127. vtkEdgeListIterator* eIt = vtkEdgeListIterator::New();
  128. inputGraph->GetEdges(eIt);
  129. do
  130. {
  131. vtkEdgeType e = eIt->Next();
  132. if (e.Id == ArcId)
  133. {
  134. if ((criticalPointIds->GetTuple(e.Source)) && (criticalPointIds->GetTuple(e.Target)))
  135. {
  136. criticalPoints.first = (int)*(criticalPointIds->GetTuple(e.Source));
  137. criticalPoints.second = (int)*(criticalPointIds->GetTuple(e.Target));
  138. }
  139. else
  140. // invalid Reeb graph
  141. return 0;
  142. }
  143. } while (eIt->HasNext());
  144. eIt->Delete();
  145. vertexIds[0] = criticalPoints.first;
  146. vertexIds[vertexIds.size() - 1] = criticalPoints.second;
  147. // NB: the vertices of vertexList are already in sorted order of function
  148. // value.
  149. for (int i = 0; i < vertexList->GetNumberOfTuples(); i++)
  150. vertexIds[i + 1] = vertexList->GetVariantValue(i).ToInt();
  151. // mark all the input triangles as non visited.
  152. for (unsigned int i = 0; i < visitedTetrahedra.size(); i++)
  153. visitedTetrahedra[i] = false;
  154. // now do the parsing
  155. double min = scalarField->GetComponent(vertexIds[0], 0),
  156. max = scalarField->GetComponent(vertexIds[vertexIds.size() - 1], 0);
  157. for (unsigned int i = 0; i < vertexIds.size(); i++)
  158. {
  159. scalarValues[i] = scalarField->GetComponent(vertexIds[i], 0);
  160. vtkIdList* starTetrahedronList = vtkIdList::New();
  161. inputMesh->GetPointCells(vertexIds[i], starTetrahedronList);
  162. for (int j = 0; j < starTetrahedronList->GetNumberOfIds(); j++)
  163. {
  164. vtkIdType tId = starTetrahedronList->GetId(j);
  165. if (!visitedTetrahedra[tId])
  166. {
  167. vtkTetra* t = vtkTetra::SafeDownCast(inputMesh->GetCell(tId));
  168. if ((scalarField->GetComponent(t->GetPointIds()->GetId(0), 0) <= scalarValues[i]) &&
  169. (scalarField->GetComponent(t->GetPointIds()->GetId(1), 0) <= scalarValues[i]) &&
  170. (scalarField->GetComponent(t->GetPointIds()->GetId(2), 0) <= scalarValues[i]) &&
  171. (scalarField->GetComponent(t->GetPointIds()->GetId(3), 0) <= scalarValues[i]) &&
  172. (scalarField->GetComponent(t->GetPointIds()->GetId(0), 0) >= min) &&
  173. (scalarField->GetComponent(t->GetPointIds()->GetId(1), 0) >= min) &&
  174. (scalarField->GetComponent(t->GetPointIds()->GetId(2), 0) >= min) &&
  175. (scalarField->GetComponent(t->GetPointIds()->GetId(3), 0) >= min))
  176. {
  177. // make sure the triangle is strictly in the covered function
  178. // span.
  179. double p0[3], p1[3], p2[3], p3[3];
  180. inputMesh->GetPoint(t->GetPointIds()->GetId(0), p0);
  181. inputMesh->GetPoint(t->GetPointIds()->GetId(1), p1);
  182. inputMesh->GetPoint(t->GetPointIds()->GetId(2), p2);
  183. inputMesh->GetPoint(t->GetPointIds()->GetId(3), p3);
  184. cumulativeVolume += vtkTetra::ComputeVolume(p0, p1, p2, p3);
  185. visitedTetrahedra[tId] = true;
  186. }
  187. }
  188. }
  189. volumeSignature[i] = cumulativeVolume;
  190. starTetrahedronList->Delete();
  191. }
  192. // now adjust to the desired sampling
  193. std::vector<std::pair<int, double>> samples(NumberOfSamples);
  194. unsigned int pos = 0;
  195. for (int i = 0; i < NumberOfSamples; i++)
  196. {
  197. samples[i].first = 0;
  198. samples[i].second = 0;
  199. double temp = min + (i + 1.0) * ((max - min) / ((double)NumberOfSamples));
  200. while ((pos < scalarValues.size()) && (scalarValues[pos] < temp))
  201. {
  202. samples[i].first++;
  203. samples[i].second += volumeSignature[pos];
  204. pos++;
  205. }
  206. if (samples[i].first)
  207. {
  208. samples[i].second /= samples[i].first;
  209. }
  210. }
  211. // no value at the start? put 0
  212. if (!samples[0].first)
  213. {
  214. samples[0].first = 1;
  215. samples[0].second = 0;
  216. }
  217. // no value at the end? put the cumulative area
  218. if (!samples[samples.size() - 1].first)
  219. {
  220. samples[samples.size() - 1].first = 1;
  221. samples[samples.size() - 1].second = cumulativeVolume;
  222. }
  223. // fill out the blanks
  224. int lastSample = 0;
  225. for (int i = 0; i < NumberOfSamples; i++)
  226. {
  227. if (!samples[i].first)
  228. {
  229. // not enough vertices in the region for the number of desired
  230. // samples. we have to interpolate.
  231. // first, search for the next valid sample
  232. int nextSample = i;
  233. for (; nextSample < NumberOfSamples; nextSample++)
  234. {
  235. if (samples[nextSample].first)
  236. break;
  237. }
  238. // next interpolate
  239. samples[i].second = samples[lastSample].second +
  240. (i - lastSample) * (samples[nextSample].second - samples[lastSample].second) /
  241. (nextSample - lastSample);
  242. }
  243. else
  244. lastSample = i;
  245. }
  246. // now prepare the output
  247. vtkVariantArray* outputSignature = vtkVariantArray::New();
  248. outputSignature->SetNumberOfTuples(static_cast<vtkIdType>(samples.size()));
  249. for (unsigned int i = 0; i < samples.size(); i++)
  250. {
  251. outputSignature->SetValue(i, samples[i].second);
  252. }
  253. output->Initialize();
  254. output->AddColumn(outputSignature);
  255. outputSignature->Delete();
  256. }
  257. return 1;
  258. }
  259. return 0;
  260. }