1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include "SMESH_FaceOrientationFilter.h"
23 #include "SMESH_ActorUtils.h"
25 #include "SUIT_Session.h"
26 #include "SUIT_ResourceMgr.h"
28 #include <vtkCellData.h>
29 #include <vtkDataSet.h>
30 #include <vtkPolyData.h>
31 #include <vtkObjectFactory.h>
32 #include <vtkInformation.h>
33 #include <vtkInformationVector.h>
35 #include <vtkFloatArray.h>
36 #include <vtkCellArray.h>
37 #include <vtkMaskPoints.h>
38 #include <vtkCellCenters.h>
39 #include <vtkGlyph3D.h>
40 #include <vtkGlyphSource2D.h>
44 #define PI 3.14159265359
46 vtkCxxRevisionMacro(SMESH_FaceOrientationFilter, "$Revision$");
47 vtkStandardNewMacro(SMESH_FaceOrientationFilter);
50 * \class SMESH_FaceOrientationFilter
51 * Passive filter take a polydata as input and create a dataset as output.
54 SMESH_FaceOrientationFilter::SMESH_FaceOrientationFilter()
56 SUIT_ResourceMgr* mgr = SUIT_Session::session()->resourceMgr();
57 myOrientationScale = mgr->doubleValue( "SMESH", "orientation_scale", 0.1 );
58 my3dVectors = mgr->booleanValue( "SMESH", "orientation_3d_vectors", false );
60 myArrowPolyData = CreateArrowPolyData();
62 myFacePolyData = vtkPolyData::New();
64 myFaceCenters = vtkCellCenters::New();
65 myFaceCenters->SetInput(myFacePolyData);
67 myFaceMaskPoints = vtkMaskPoints::New();
68 myFaceMaskPoints->SetInput(myFaceCenters->GetOutput());
69 myFaceMaskPoints->SetOnRatio(1);
71 myGlyphSource = vtkGlyphSource2D::New();
72 myGlyphSource->SetGlyphTypeToThickArrow();
73 myGlyphSource->SetFilled(0);
74 myGlyphSource->SetCenter(0.5, 0.0, 0.0);
76 myBaseGlyph = vtkGlyph3D::New();
77 myBaseGlyph->SetInput(myFaceMaskPoints->GetOutput());
78 myBaseGlyph->SetVectorModeToUseVector();
79 myBaseGlyph->SetScaleModeToDataScalingOff();
80 myBaseGlyph->SetColorModeToColorByScalar();
81 myBaseGlyph->SetSource(my3dVectors ? myArrowPolyData : myGlyphSource->GetOutput());
84 SMESH_FaceOrientationFilter::~SMESH_FaceOrientationFilter()
86 myArrowPolyData->Delete();
87 myFacePolyData->Delete();
88 myFaceCenters->Delete();
89 myFaceMaskPoints->Delete();
90 myGlyphSource->Delete();
91 myBaseGlyph->Delete();
94 void SMESH_FaceOrientationFilter::SetOrientationScale( vtkFloatingPointType theScale )
96 myOrientationScale = theScale;
100 void SMESH_FaceOrientationFilter::Set3dVectors( bool theState )
102 my3dVectors = theState;
103 myBaseGlyph->SetSource(my3dVectors ? myArrowPolyData : myGlyphSource->GetOutput());
107 vtkPolyData* SMESH_FaceOrientationFilter::CreateArrowPolyData()
109 vtkPoints* points = vtkPoints::New();
110 vtkCellArray* polys = vtkCellArray::New();
117 float angle = 2. * PI / n;
122 float p0[3] = { 0.0, 0.0, 0.0 };
123 float p1[3] = { l1, 0.0, 0.0 };
124 float p2[3] = { l2, 0.0, 0.0 };
126 points->InsertPoint( 0, p0 );
127 points->InsertPoint( 1, p1 );
128 points->InsertPoint( 2, p2 );
131 for( int i = 0; i < n; i++ )
134 p[1] = r1 * sin( i * angle );
135 p[2] = r1 * cos( i * angle );
136 points->InsertPoint( i + 3, p );
139 points->InsertPoint( i + 3 + n, p );
142 // insert the last cells outside a loop
147 polys->InsertNextCell( 3, c3 );
151 c4[2] = 3 + 2 * n - 1;
153 polys->InsertNextCell( 4, c4 );
155 for( int i = 0; i < n - 1; i++ )
160 polys->InsertNextCell( 3, c3 );
166 polys->InsertNextCell( 4, c4 );
170 for( int i = 0; i < n; i++ )
173 p[1] = r2 * sin( i * angle );
174 p[2] = r2 * cos( i * angle );
175 points->InsertPoint( i + 3 + 2 * n, p );
178 // insert the last cells outside a loop
182 c3[2] = 3 + 2 * n + n - 1;
183 polys->InsertNextCell( 3, c3 );
186 polys->InsertNextCell( 3, c3 );
188 for( int i = 0; i < n - 1; i++ )
191 c3[1] = 3 + i + 2 * n;
192 c3[2] = 3 + i + 2 * n + 1;
193 polys->InsertNextCell( 3, c3 );
196 polys->InsertNextCell( 3, c3 );
199 vtkPolyData* aPolyData = vtkPolyData::New();
201 aPolyData->SetPoints(points);
204 aPolyData->SetPolys(polys);
210 void GetFaceParams( vtkCell* theFace, double theNormal[3], double& theSize )
212 vtkPoints* aPoints = theFace->GetPoints();
214 // here we get first 3 points from the face and calculate the normal as a cross-product of vectors
215 double x0 = aPoints->GetPoint(0)[0], y0 = aPoints->GetPoint(0)[1], z0 = aPoints->GetPoint(0)[2];
216 double x1 = aPoints->GetPoint(1)[0], y1 = aPoints->GetPoint(1)[1], z1 = aPoints->GetPoint(1)[2];
217 double x2 = aPoints->GetPoint(2)[0], y2 = aPoints->GetPoint(2)[1], z2 = aPoints->GetPoint(2)[2];
219 theNormal[0] = ( y1 - y0 ) * ( z2 - z0 ) - ( z1 - z0 ) * ( y2 - y0 );
220 theNormal[1] = ( z1 - z0 ) * ( x2 - x0 ) - ( x1 - x0 ) * ( z2 - z0 );
221 theNormal[2] = ( x1 - x0 ) * ( y2 - y0 ) - ( y1 - y0 ) * ( x2 - x0 );
223 double* aBounds = theFace->GetBounds();
224 theSize = pow( pow( aBounds[1] - aBounds[0], 2 ) +
225 pow( aBounds[3] - aBounds[2], 2 ) +
226 pow( aBounds[5] - aBounds[4], 2 ), 0.5 );
230 * Execute method. Output calculation.
232 int SMESH_FaceOrientationFilter::RequestData(
233 vtkInformation *request,
234 vtkInformationVector **inputVector,
235 vtkInformationVector *outputVector)
237 // get the info objects
238 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
239 vtkInformation *outInfo = outputVector->GetInformationObject(0);
241 // get the input and ouptut
242 vtkDataSet *input = vtkDataSet::SafeDownCast(
243 inInfo->Get(vtkDataObject::DATA_OBJECT()));
244 vtkPolyData *output = vtkPolyData::SafeDownCast(
245 outInfo->Get(vtkDataObject::DATA_OBJECT()));
247 myFacePolyData->Initialize();
248 myFacePolyData->ShallowCopy(input);
250 vtkCellArray* aFaces = vtkCellArray::New();
252 vtkFloatArray* aVectors = vtkFloatArray::New();
253 aVectors->SetNumberOfComponents(3);
256 double anAverageSize = 0;
258 vtkIdList* aNeighborIds = vtkIdList::New();
260 for(int aCellId = 0, aNbCells = input->GetNumberOfCells(); aCellId < aNbCells; aCellId++)
262 vtkCell* aCell = input->GetCell(aCellId);
264 if( aCell->GetNumberOfFaces() == 0 && aCell->GetNumberOfPoints() > 2 ) // cell is a face
266 double aSize, aNormal[3];
267 GetFaceParams( aCell, aNormal, aSize );
269 aFaces->InsertNextCell(aCell);
270 aVectors->InsertNextTuple(aNormal);
273 anAverageSize += aSize;
278 for(int aFaceId = 0, aNbFaces = aCell->GetNumberOfFaces(); aFaceId < aNbFaces; aFaceId++)
280 vtkCell* aFace = aCell->GetFace(aFaceId);
282 input->GetCellNeighbors( aCellId, aFace->PointIds, aNeighborIds );
283 if( aNeighborIds->GetNumberOfIds() > 0 )
286 double aSize, aNormal[3];
287 GetFaceParams( aFace, aNormal, aSize );
289 aFaces->InsertNextCell(aFace->GetPointIds());
290 aVectors->InsertNextTuple(aNormal);
293 anAverageSize += aSize;
296 aNeighborIds->Delete();
298 myFacePolyData->SetPolys(aFaces);
301 myFacePolyData->GetCellData()->SetScalars(0);
302 myFacePolyData->GetCellData()->SetVectors(aVectors);
305 if( anAllFaces == 0 )
308 anAverageSize /= anAllFaces;
309 anAverageSize *= myOrientationScale;
311 myBaseGlyph->SetScaleFactor( anAverageSize );
312 myBaseGlyph->Update();
314 output->ShallowCopy( myBaseGlyph->GetOutput() );
319 int SMESH_FaceOrientationFilter::FillInputPortInformation(int, vtkInformation *info)
321 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");