1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkDistancePolyDataFilter.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkDistancePolyDataFilter.h"
16 
17 #include "vtkCellData.h"
18 #include "vtkDoubleArray.h"
19 #include "vtkImplicitPolyDataDistance.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationVector.h"
22 #include "vtkObjectFactory.h"
23 #include "vtkPointData.h"
24 #include "vtkStreamingDemandDrivenPipeline.h"
25 #include "vtkTriangle.h"
26 
27 vtkStandardNewMacro(vtkDistancePolyDataFilter);
28 
29 //-----------------------------------------------------------------------------
vtkDistancePolyDataFilter()30 vtkDistancePolyDataFilter::vtkDistancePolyDataFilter() : vtkPolyDataAlgorithm()
31 {
32   this->SignedDistance = 1;
33   this->NegateDistance = 0;
34   this->ComputeSecondDistance = 1;
35 
36   this->SetNumberOfInputPorts(2);
37   this->SetNumberOfOutputPorts(2);
38 }
39 
40 //-----------------------------------------------------------------------------
~vtkDistancePolyDataFilter()41 vtkDistancePolyDataFilter::~vtkDistancePolyDataFilter()
42 {
43 }
44 
45 
46 //-----------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)47 int vtkDistancePolyDataFilter::RequestData(vtkInformation*        vtkNotUsed(request),
48                                            vtkInformationVector** inputVector,
49                                            vtkInformationVector*  outputVector)
50 {
51   vtkPolyData *input0 = vtkPolyData::GetData(inputVector[0], 0);
52   vtkPolyData *input1 = vtkPolyData::GetData(inputVector[1], 0);
53   vtkPolyData* output0 = vtkPolyData::GetData(outputVector, 0);
54   vtkPolyData* output1 = vtkPolyData::GetData(outputVector, 1);
55 
56   output0->CopyStructure(input0);
57   output0->GetPointData()->PassData(input0->GetPointData());
58   output0->GetCellData()->PassData(input0->GetCellData());
59   output0->BuildCells();
60   this->GetPolyDataDistance(output0, input1);
61 
62   if (this->ComputeSecondDistance)
63     {
64     output1->CopyStructure(input1);
65     output1->GetPointData()->PassData(input1->GetPointData());
66     output1->GetCellData()->PassData(input1->GetCellData());
67     output1->BuildCells();
68     this->GetPolyDataDistance(output1, input0);
69     }
70   return 1;
71 }
72 
73 //-----------------------------------------------------------------------------
GetPolyDataDistance(vtkPolyData * mesh,vtkPolyData * src)74 void vtkDistancePolyDataFilter::GetPolyDataDistance(vtkPolyData* mesh, vtkPolyData* src)
75 {
76   vtkDebugMacro(<<"Start vtkDistancePolyDataFilter::GetPolyDataDistance");
77 
78   if (mesh->GetNumberOfPolys() == 0 || mesh->GetNumberOfPoints() == 0)
79     {
80     vtkErrorMacro(<<"No points/cells to operate on");
81     return;
82     }
83 
84   if (src->GetNumberOfPolys() == 0 || src->GetNumberOfPoints() == 0)
85     {
86     vtkErrorMacro(<<"No points/cells to difference from");
87     return;
88     }
89 
90   vtkImplicitPolyDataDistance* imp = vtkImplicitPolyDataDistance::New();
91   imp->SetInput( src );
92 
93   // Calculate distance from points.
94   int numPts = mesh->GetNumberOfPoints();
95 
96   vtkDoubleArray* pointArray = vtkDoubleArray::New();
97   pointArray->SetName( "Distance" );
98   pointArray->SetNumberOfComponents( 1 );
99   pointArray->SetNumberOfTuples( numPts );
100 
101   for (vtkIdType ptId = 0; ptId < numPts; ptId++)
102     {
103     double pt[3];
104     mesh->GetPoint( ptId, pt );
105     double val = imp->EvaluateFunction( pt );
106     double dist = SignedDistance ? (NegateDistance ? -val : val) : fabs(val);
107     pointArray->SetValue( ptId, dist );
108     }
109 
110   mesh->GetPointData()->AddArray( pointArray );
111   pointArray->Delete();
112   mesh->GetPointData()->SetActiveScalars( "Distance" );
113 
114   // Calculate distance from cell centers.
115   int numCells = mesh->GetNumberOfCells();
116 
117   vtkDoubleArray* cellArray = vtkDoubleArray::New();
118   cellArray->SetName( "Distance" );
119   cellArray->SetNumberOfComponents( 1 );
120   cellArray->SetNumberOfTuples( numCells );
121 
122   for (vtkIdType cellId = 0; cellId < numCells; cellId++)
123     {
124     vtkCell *cell = mesh->GetCell( cellId );
125     int subId;
126     double pcoords[3], x[3], weights[256];
127 
128     cell->GetParametricCenter( pcoords );
129     cell->EvaluateLocation( subId, pcoords, x, weights );
130 
131     double val = imp->EvaluateFunction( x );
132     double dist = SignedDistance ? (NegateDistance ? -val : val) : fabs(val);
133     cellArray->SetValue( cellId, dist );
134     }
135 
136   mesh->GetCellData()->AddArray( cellArray );
137   cellArray->Delete();
138   mesh->GetCellData()->SetActiveScalars("Distance");
139 
140   imp->Delete();
141 
142   vtkDebugMacro(<<"End vtkDistancePolyDataFilter::GetPolyDataDistance");
143 }
144 
145 //-----------------------------------------------------------------------------
GetSecondDistanceOutput()146 vtkPolyData* vtkDistancePolyDataFilter::GetSecondDistanceOutput()
147 {
148   if (!this->ComputeSecondDistance)
149     {
150     return 0;
151     }
152   return vtkPolyData::SafeDownCast(this->GetOutputDataObject(1));
153 }
154 
155 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)156 void vtkDistancePolyDataFilter::PrintSelf(ostream& os, vtkIndent indent)
157 {
158   this->Superclass::PrintSelf(os,indent);
159   os << indent << "SignedDistance: " << this->SignedDistance << "\n";
160   os << indent << "NegateDistance: " << this->NegateDistance << "\n";
161   os << indent << "ComputeSecondDistance: " << this->ComputeSecondDistance << "\n";
162 }
163