00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mitkPolygonToRingFilter.h"
00019 #include "mitkMesh.h"
00020 #include "mitkSurface.h"
00021 #include "mitkPlaneGeometry.h"
00022
00023 #include <vnl/vnl_cross.h>
00024 #include <vnl/vnl_quaternion.h>
00025 #include <vnl/vnl_quaternion.txx>
00026
00027 #include <vtkPolyData.h>
00028 #include <vtkPoints.h>
00029 #include <vtkCellArray.h>
00030 #include <vtkCardinalSpline.h>
00031
00032 #include <vector>
00033
00034
00035 mitk::PolygonToRingFilter::PolygonToRingFilter()
00036 : m_RingRadius(3.5f), m_RingResolution(30), m_SplineResolution(20)
00037 {
00038 m_SplineX = vtkCardinalSpline::New();
00039 m_SplineY = vtkCardinalSpline::New();
00040 m_SplineZ = vtkCardinalSpline::New();
00041 }
00042
00043 mitk::PolygonToRingFilter::~PolygonToRingFilter()
00044 {
00045 m_SplineX->Delete();
00046 m_SplineY->Delete();
00047 m_SplineZ->Delete();
00048 }
00049
00050 void mitk::PolygonToRingFilter::GenerateOutputInformation()
00051 {
00052 mitk::Mesh::ConstPointer input = this->GetInput();
00053 mitk::Surface::Pointer output = this->GetOutput();
00054
00055 itkDebugMacro(<<"GenerateOutputInformation()");
00056
00057 if(input.IsNull()) return;
00058
00059 output->SetGeometry(static_cast<Geometry3D*>(input->GetGeometry()->Clone().GetPointer()));
00060
00061 output->Expand( input->GetPointSetSeriesSize() );
00062 }
00063
00064 void mitk::PolygonToRingFilter::GenerateData()
00065 {
00066 mitk::Mesh::ConstPointer input = this->GetInput();
00067 mitk::Surface::Pointer output = this->GetOutput();
00068
00069 unsigned int t;
00070 for ( t = 0; t < input->GetPointSetSeriesSize(); ++t )
00071 {
00072
00073 vtkPolyData *polyData = vtkPolyData::New();
00074 vtkPoints *vPoints = vtkPoints::New();
00075 vtkCellArray *polys = vtkCellArray::New();
00076
00077 mitk::Mesh::PointType thisPoint;
00078
00079
00080 Mesh::ConstCellIterator cellIt, cellEnd;
00081 cellEnd = input->GetMesh( t )->GetCells()->End();
00082 for ( cellIt = input->GetMesh( t )->GetCells()->Begin();
00083 cellIt != cellEnd;
00084 ++cellIt )
00085 {
00086 m_PointList.clear();
00087 m_VectorList.clear();
00088
00089 this->BuildPointAndVectorList(
00090 *cellIt->Value(), m_PointList, m_VectorList, t );
00091 this->BuildVtkTube( vPoints, polys, m_PointList, m_VectorList );
00092 }
00093
00094 polyData->SetPoints( vPoints );
00095 vPoints->Delete();
00096 polyData->SetPolys( polys );
00097 polys->Delete();
00098
00099 output->SetVtkPolyData( polyData, t );
00100 polyData->Delete();
00101
00102 }
00103
00104 }
00105
00106
00107
00108
00109
00110
00111
00112 void mitk::PolygonToRingFilter::DrawCyl(vtkPoints *vPoints, vtkCellArray *polys,
00113 VectorListType &sl, VectorListType &sc, int idmax, Point3D & last_p, Point3D & cur_p)
00114 {
00115 unsigned int i;
00116
00117 VectorListType::iterator slit=sl.begin(), scit=sc.begin(), scend=sc.end();
00118 scit+=idmax;
00119 Point3D a,b;
00120 Point3D a_first,b_first;
00121 int a_firstID = 0, b_firstID = 0;
00122
00123 vtkIdType front[4];
00124 for(i=0;i<m_RingResolution;++i)
00125 {
00126 VnlVector v0,v1,v2,v3,normal;
00127 v0=a.Get_vnl_vector(); v1=b.Get_vnl_vector();
00128 a=last_p+*slit*m_RingRadius; b=cur_p+*scit*m_RingRadius;
00129 v2=b.Get_vnl_vector(); v3=a.Get_vnl_vector();
00130 normal=vnl_cross_3d(v1-v0,v3-v0);
00131
00132 if(i!=0)
00133 {
00134 front[3]=vPoints->InsertNextPoint(v0[0],v0[1],v0[2]);
00135 front[2]=vPoints->InsertNextPoint(v1[0],v1[1],v1[2]);
00136 front[1]=vPoints->InsertNextPoint(v2[0],v2[1],v2[2]);
00137 front[0]=vPoints->InsertNextPoint(v3[0],v3[1],v3[2]);
00138 polys->InsertNextCell( (vtkIdType) 4, front );
00139 if(i==1)
00140 {
00141 a_firstID=front[3]; b_firstID=front[2];
00142 }
00143 }
00144
00145 ++slit; ++scit; if(scit==scend) scit=sc.begin();
00146 }
00147 front[3]=front[0];
00148 front[2]=front[1];
00149 front[1]=b_firstID;
00150 front[0]=a_firstID;
00151 polys->InsertNextCell( 4, front );
00152 }
00153
00154
00155 void mitk::PolygonToRingFilter::BuildVtkTube(vtkPoints *vPoints, vtkCellArray *polys, PointListType& ptList, VectorListType& vecList)
00156 {
00157 PointListType::iterator pit = ptList.begin(), pend = ptList.end();
00158 VectorListType::iterator vit = vecList.begin();
00159
00160 Vector3D axis, last_v, next_v, s;
00161 Point3D cur_p,last_p;
00162
00163
00164 VectorListType *sl, *sc, *swp, sfirst, buf1, buf2;
00165 sl=&buf1; sc=&buf2;
00166
00167 Vector3D a,b;
00168 Matrix3D m;
00169
00170
00171
00172
00173
00174
00175
00176 last_v=vecList.back(); next_v=*vit; s.Set_vnl_vector( vnl_cross_3d(last_v.Get_vnl_vector(),next_v.Get_vnl_vector()) ); s.Normalize();
00177 a=last_v; b=next_v; a.Normalize(); b.Normalize(); axis=a+b; axis.Normalize();
00178
00179
00180 m = vnl_quaternion<mitk::ScalarType>(axis.Get_vnl_vector(),2*vnl_math::pi/(double)m_RingResolution).rotation_matrix_transpose();
00181 unsigned int i;
00182 for(i=0;i<m_RingResolution;++i)
00183 {
00184 sfirst.push_back(s);
00185 s=m*s;
00186 }
00187 *sl=sfirst;
00188 last_p=*pit;
00189 ++pit; ++vit;
00190
00191
00192 for ( ; pit != pend; ++pit, ++vit )
00193 {
00194
00195 cur_p=*pit; last_v=next_v; next_v=*vit; s.Set_vnl_vector( vnl_cross_3d(last_v.Get_vnl_vector(),next_v.Get_vnl_vector()) ); s.Normalize();
00196
00197 a=last_v; b=next_v; a.Normalize(); b.Normalize(); axis=a+b; axis.Normalize();
00198
00199
00200 double max=0; int idmax=0; Vector3D sl0=*(sl->begin());
00201 m = vnl_quaternion<mitk::ScalarType>(axis.Get_vnl_vector(),2*vnl_math::pi/(double)m_RingResolution).rotation_matrix_transpose();
00202 for(i=0;i<m_RingResolution;++i)
00203 {
00204 sc->push_back(s);
00205 double tmp=s*sl0;
00206 if(tmp>max)
00207 {
00208 max=tmp;
00209 idmax=i;
00210 }
00211 s=m*s;
00212 }
00213
00214
00215
00216
00217
00218
00219 DrawCyl(vPoints, polys, *sl, *sc, idmax, last_p, cur_p);
00220
00221
00222 last_p=cur_p;
00223 swp=sl; sl=sc; sc=swp; sc->clear();
00224 }
00225
00226
00227 double max=0; int idmax=0; Vector3D sl0=*(sl->begin());
00228 for(i=0;i<m_RingResolution;++i)
00229 {
00230 s=sfirst[i];
00231 double tmp=s*sl0;
00232 if(tmp>max)
00233 {
00234 max=tmp;
00235 idmax=i;
00236 }
00237 }
00238 cur_p=*ptList.begin();
00239 DrawCyl(vPoints, polys, *sl, sfirst, idmax, last_p, cur_p);
00240 }
00241
00242 void
00243 mitk::PolygonToRingFilter
00244 ::BuildPointAndVectorList( mitk::Mesh::CellType& cell,
00245 PointListType& ptList, VectorListType& vecList, int timeStep )
00246 {
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 m_SplineX->RemoveAllPoints();
00265 m_SplineY->RemoveAllPoints();
00266 m_SplineZ->RemoveAllPoints();
00267
00268 int numberOfPoints = cell.GetNumberOfPoints();
00269
00270 Mesh::PointType inputPoint;
00271 vtkFloatingPointType t, tStart(0), tEnd(0);
00272
00273
00274
00275 int i;
00276 Mesh::PointIdIterator pit = cell.PointIdsEnd() - 3;
00277 for ( i = -3, t = 0.0; i < numberOfPoints + 3; ++i )
00278 {
00279 if ( i == 0 ) { tStart = t; }
00280 if ( i == numberOfPoints ) { tEnd = t; }
00281
00282 inputPoint = this->GetInput()->GetPoint( *pit, timeStep );
00283 m_SplineX->AddPoint( t, inputPoint[0] );
00284 m_SplineY->AddPoint( t, inputPoint[1] );
00285 m_SplineZ->AddPoint( t, inputPoint[2] );
00286
00287 ++pit;
00288 if ( pit == cell.PointIdsEnd() )
00289 {
00290 pit = cell.PointIdsBegin();
00291 }
00292
00293 t += inputPoint.EuclideanDistanceTo(
00294 this->GetInput()->GetPoint( *pit, timeStep ) );
00295 }
00296
00297
00298
00299 Point3D point, firstPoint, lastPoint;
00300 firstPoint.Fill(0);
00301 lastPoint.Fill(0);
00302 int numberOfSegments = numberOfPoints * m_SplineResolution;
00303 vtkFloatingPointType step = (tEnd - tStart) / numberOfSegments;
00304 for ( i = 0, t = tStart; i < numberOfSegments; ++i, t += step )
00305 {
00306 FillVector3D( point,
00307 m_SplineX->Evaluate(t), m_SplineY->Evaluate(t), m_SplineZ->Evaluate(t)
00308 );
00309
00310 ptList.push_back( point );
00311
00312 if ( i == 0 )
00313 {
00314 firstPoint = point;
00315 }
00316 else
00317 {
00318 vecList.push_back( point - lastPoint );
00319 }
00320 lastPoint = point;
00321 }
00322 vecList.push_back( firstPoint - lastPoint );
00323 }
00324
00325
00326 const mitk::Mesh *mitk::PolygonToRingFilter::GetInput(void)
00327 {
00328 if (this->GetNumberOfInputs() < 1)
00329 {
00330 return 0;
00331 }
00332
00333 return static_cast<const mitk::Mesh * >
00334 (this->ProcessObject::GetInput(0) );
00335 }
00336
00337 void mitk::PolygonToRingFilter::SetInput(const mitk::Mesh *input)
00338 {
00339
00340 this->ProcessObject::SetNthInput(0,
00341 const_cast< mitk::Mesh * >( input ) );
00342 }