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 // VISU OBJECT : interactive object for VISU entities implementation
23 // File: VISU_LabelPointsFilter.cxx
24 // Author: Vitaly Smetannikov
27 #include "VISU_LabelPointsFilter.hxx"
29 #include <vtkPolyData.h>
30 #include <vtkObjectFactory.h>
31 #include <vtkInformation.h>
32 #include <vtkInformationVector.h>
33 #include <vtkFeatureEdges.h>
34 #include <vtkCellArray.h>
35 #include <vtkPointData.h>
36 #include <vtkCellData.h>
37 #include <vtkDataArray.h>
38 #include <vtkDoubleArray.h>
39 #include <vtkGeometryFilter.h>
40 #include <vtkPolyDataConnectivityFilter.h>
47 #define CONTAINS(SET, PT) (SET.find(PT) != SET.end())
51 bool operator()(const vtkIdType a1, const vtkIdType a2) const
59 //----------------------------------------------------------------------------
60 vtkStandardNewMacro(VISU_LabelPointsFilter);
63 //----------------------------------------------------------------------------
64 void VISU_LabelPointsFilter::SetPointsNb(int theNb)
66 if (myPointsNb == theNb) return;
67 myPointsNb = (theNb < 1)? 1:theNb;
71 //----------------------------------------------------------------------------
72 VISU_LabelPointsFilter::VISU_LabelPointsFilter():
73 vtkPolyDataAlgorithm(),
78 //----------------------------------------------------------------------------
79 VISU_LabelPointsFilter::~VISU_LabelPointsFilter()
84 //----------------------------------------------------------------------------
85 int VISU_LabelPointsFilter::RequestData(vtkInformation* vtkNotUsed(request),
86 vtkInformationVector** inputVector,
87 vtkInformationVector* outputVector)
89 // get the info objects
90 vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
91 vtkInformation* outInfo = outputVector->GetInformationObject(0);
93 // get the input and ouptut
94 vtkPolyData* input = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
95 vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
97 GetRegions(input, output);
102 int VISU_LabelPointsFilter::RequestUpdateExtent(vtkInformation* vtkNotUsed(request),
103 vtkInformationVector** inputVector,
104 vtkInformationVector* outputVector)
106 // get the info objects
107 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
108 vtkInformation *outInfo = outputVector->GetInformationObject(0);
110 vtkPolyData* input = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
111 vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
113 GetRegions(input, output);
119 int VISU_LabelPointsFilter::GetRegions(vtkPolyData* theInput,
120 vtkPolyData* theOutput)
123 vtkIdType numPts, numCells;
126 vtkPointData *aInpPD=theInput->GetPointData(), *aOutPD=theOutput->GetPointData();
127 vtkCellData *aInpCD=theInput->GetCellData(), *aOutCD=theOutput->GetCellData();
129 // Check input/allocate storage
131 inPts = theInput->GetPoints();
136 numPts = inPts->GetNumberOfPoints();
137 numCells = theInput->GetNumberOfCells();
139 if ( numPts < 1 || numCells < 1 )
142 // Build cell structure
144 vtkPolyData* aMesh = vtkPolyData::New();
145 aMesh->CopyStructure(theInput);
148 // Initialize. Keep track of points and cells visited.
150 vtkIdTypeArray* aRegionSizes = vtkIdTypeArray::New();
151 int* aVisited = new int[numCells];
152 for ( i=0; i < numCells; i++ )
155 vtkIdType* aPointMap = new vtkIdType[numPts];
156 for ( i=0; i < numPts; i++ )
159 vtkPoints* newPts = vtkPoints::New();
160 newPts->Allocate(numPts);
162 // Traverse all cells marking those visited. Each new search
163 // starts a new connected region. Connected region grows
164 // using a connected wave propagation.
166 vtkIdList* aWave = vtkIdList::New();
167 aWave->Allocate(numPts/4+1,numPts);
168 vtkIdList* aWave2 = vtkIdList::New();
169 aWave2->Allocate(numPts/4+1,numPts);
171 vtkIdType aPointNumber = 0;
172 int aRegionNumber = 0;
174 vtkIdList* aCellIds = vtkIdList::New();
175 aCellIds->Allocate(8, VTK_CELL_SIZE);
176 vtkIdList* aPointIds = vtkIdList::New();
177 aPointIds->Allocate(8, VTK_CELL_SIZE);
179 // vtkIdType aNumCellsInRegion;
181 aOutPD->CopyAllocate(aInpPD);
182 aOutCD->CopyAllocate(aInpCD);
184 //visit all cells marking with region number
185 for (cellId=0; cellId < numCells; cellId++) {
186 if ( aVisited[cellId] < 0 ) {
187 aWave->InsertNextId(cellId);
189 TraverseAndMark(aWave, aWave2, aVisited, aPointMap,
190 aRegionNumber, aPointNumber, aMesh);
192 if (aPointNumber >= myPointsNb) {
193 std::set<vtkIdType, ltIdType> aIdxSet;
194 for (i=0; i < numPts; i++) {
195 if ( aPointMap[i] > -1 ) {
200 std::vector<vtkIdType> aIdx(aIdxSet.begin(), aIdxSet.end());
201 int aActualPts = aIdx.size();
203 if (myPointsNb > 2) {
204 int k = aActualPts/(myPointsNb - 1);
206 for (i=0, count = 0; i < aActualPts; i+=k, count++) {
207 aNewId = newPts->InsertNextPoint(inPts->GetPoint(aIdx[i]));
208 aOutPD->CopyData(aInpPD, aIdx[i], aNewId);
210 if (count < myPointsNb) {
211 aNewId = newPts->InsertNextPoint(inPts->GetPoint(aIdx[aActualPts - 1]));
212 aOutPD->CopyData(aInpPD, aIdx[aActualPts - 1], aNewId);
215 aNewId = newPts->InsertNextPoint(inPts->GetPoint(aIdx[0]));
216 aOutPD->CopyData(aInpPD, aIdx[0], aNewId);
217 if (myPointsNb == 2) {
218 aNewId = newPts->InsertNextPoint(inPts->GetPoint(aIdx[aActualPts - 1]));
219 aOutPD->CopyData(aInpPD, aIdx[aActualPts - 1], aNewId);
231 theOutput->SetPoints(newPts);
238 theOutput->Squeeze();
242 return aRegionSizes->GetMaxId() + 1;
246 // Mark current cell as visited and assign region number. Note:
247 // traversal occurs across shared vertices.
249 void VISU_LabelPointsFilter::TraverseAndMark (vtkIdList* theWave,
252 vtkIdType* thePointMap,
253 int& theRegionNumber,
254 vtkIdType& thePointNumber,
255 vtkPolyData* theMesh)
257 vtkIdType cellId, ptId, numIds, i;
259 vtkIdType *pts, *cells, npts;
261 unsigned short ncells;
262 vtkIdList* aNeighborCellPointIds = vtkIdList::New();
265 while ( (numIds=theWave->GetNumberOfIds()) > 0 ) {
266 for ( i=0; i < numIds; i++ ) {
267 cellId = theWave->GetId(i);
268 if ( theVisited[cellId] < 0 ) {
269 theVisited[cellId] = theRegionNumber;
270 theMesh->GetCellPoints(cellId, npts, pts);
272 for (j=0; j < npts; j++) {
273 if ( thePointMap[ptId=pts[j]] < 0 ) {
274 thePointMap[ptId] = thePointNumber++;
276 theMesh->GetPointCells(ptId,ncells,cells);
278 // check connectivity criterion (geometric + scalar)
279 for (k=0; k < ncells; k++) {
281 theWave2->InsertNextId(cellId);
283 }//for all cells using this point
284 }//for all points of this cell
285 }//if cell not yet visited
286 }//for all cells in this wave
292 } //while wave is not empty