1 // Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // VISU OBJECT : interactive object for VISU entities implementation
21 // File: VISU_LabelPointsFilter.cxx
22 // Author: Vitaly Smetannikov
25 #include "VISU_LabelPointsFilter.hxx"
27 #include <vtkPolyData.h>
28 #include <vtkObjectFactory.h>
29 #include <vtkInformation.h>
30 #include <vtkInformationVector.h>
31 #include <vtkFeatureEdges.h>
32 #include <vtkCellArray.h>
33 #include <vtkPointData.h>
34 #include <vtkCellData.h>
35 #include <vtkDataArray.h>
36 #include <vtkDoubleArray.h>
37 #include <vtkGeometryFilter.h>
38 #include <vtkPolyDataConnectivityFilter.h>
45 #define CONTAINS(SET, PT) (SET.find(PT) != SET.end())
49 bool operator()(const vtkIdType a1, const vtkIdType a2) const
57 //----------------------------------------------------------------------------
58 vtkStandardNewMacro(VISU_LabelPointsFilter);
61 //----------------------------------------------------------------------------
62 void VISU_LabelPointsFilter::SetPointsNb(int theNb)
64 if (myPointsNb == theNb) return;
65 myPointsNb = (theNb < 1)? 1:theNb;
69 //----------------------------------------------------------------------------
70 VISU_LabelPointsFilter::VISU_LabelPointsFilter():
71 vtkPolyDataAlgorithm(),
76 //----------------------------------------------------------------------------
77 VISU_LabelPointsFilter::~VISU_LabelPointsFilter()
82 //----------------------------------------------------------------------------
83 int VISU_LabelPointsFilter::RequestData(vtkInformation* vtkNotUsed(request),
84 vtkInformationVector** inputVector,
85 vtkInformationVector* outputVector)
87 // get the info objects
88 vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
89 vtkInformation* outInfo = outputVector->GetInformationObject(0);
91 // get the input and ouptut
92 vtkPolyData* input = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
93 vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
95 GetRegions(input, output);
100 int VISU_LabelPointsFilter::RequestUpdateExtent(vtkInformation* vtkNotUsed(request),
101 vtkInformationVector** inputVector,
102 vtkInformationVector* outputVector)
104 // get the info objects
105 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
106 vtkInformation *outInfo = outputVector->GetInformationObject(0);
108 vtkPolyData* input = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
109 vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
111 GetRegions(input, output);
117 int VISU_LabelPointsFilter::GetRegions(vtkPolyData* theInput,
118 vtkPolyData* theOutput)
121 vtkIdType numPts, numCells;
124 vtkPointData *aInpPD=theInput->GetPointData(), *aOutPD=theOutput->GetPointData();
125 vtkCellData *aInpCD=theInput->GetCellData(), *aOutCD=theOutput->GetCellData();
127 // Check input/allocate storage
129 inPts = theInput->GetPoints();
134 numPts = inPts->GetNumberOfPoints();
135 numCells = theInput->GetNumberOfCells();
137 if ( numPts < 1 || numCells < 1 )
140 // Build cell structure
142 vtkPolyData* aMesh = vtkPolyData::New();
143 aMesh->CopyStructure(theInput);
146 // Initialize. Keep track of points and cells visited.
148 vtkIdTypeArray* aRegionSizes = vtkIdTypeArray::New();
149 int* aVisited = new int[numCells];
150 for ( i=0; i < numCells; i++ )
153 vtkIdType* aPointMap = new vtkIdType[numPts];
154 for ( i=0; i < numPts; i++ )
157 vtkPoints* newPts = vtkPoints::New();
158 newPts->Allocate(numPts);
160 // Traverse all cells marking those visited. Each new search
161 // starts a new connected region. Connected region grows
162 // using a connected wave propagation.
164 vtkIdList* aWave = vtkIdList::New();
165 aWave->Allocate(numPts/4+1,numPts);
166 vtkIdList* aWave2 = vtkIdList::New();
167 aWave2->Allocate(numPts/4+1,numPts);
169 vtkIdType aPointNumber = 0;
170 int aRegionNumber = 0;
172 vtkIdList* aCellIds = vtkIdList::New();
173 aCellIds->Allocate(8, VTK_CELL_SIZE);
174 vtkIdList* aPointIds = vtkIdList::New();
175 aPointIds->Allocate(8, VTK_CELL_SIZE);
177 // vtkIdType aNumCellsInRegion;
179 aOutPD->CopyAllocate(aInpPD);
180 aOutCD->CopyAllocate(aInpCD);
182 //visit all cells marking with region number
183 for (cellId=0; cellId < numCells; cellId++) {
184 if ( aVisited[cellId] < 0 ) {
185 aWave->InsertNextId(cellId);
187 TraverseAndMark(aWave, aWave2, aVisited, aPointMap,
188 aRegionNumber, aPointNumber, aMesh);
190 if (aPointNumber >= myPointsNb) {
191 std::set<vtkIdType, ltIdType> aIdxSet;
192 for (i=0; i < numPts; i++) {
193 if ( aPointMap[i] > -1 ) {
198 std::vector<vtkIdType> aIdx(aIdxSet.begin(), aIdxSet.end());
199 int aActualPts = aIdx.size();
201 if (myPointsNb > 2) {
202 int k = aActualPts/(myPointsNb - 1);
204 for (i=0, count = 0; i < aActualPts; i+=k, count++) {
205 aNewId = newPts->InsertNextPoint(inPts->GetPoint(aIdx[i]));
206 aOutPD->CopyData(aInpPD, aIdx[i], aNewId);
208 if (count < myPointsNb) {
209 aNewId = newPts->InsertNextPoint(inPts->GetPoint(aIdx[aActualPts - 1]));
210 aOutPD->CopyData(aInpPD, aIdx[aActualPts - 1], aNewId);
213 aNewId = newPts->InsertNextPoint(inPts->GetPoint(aIdx[0]));
214 aOutPD->CopyData(aInpPD, aIdx[0], aNewId);
215 if (myPointsNb == 2) {
216 aNewId = newPts->InsertNextPoint(inPts->GetPoint(aIdx[aActualPts - 1]));
217 aOutPD->CopyData(aInpPD, aIdx[aActualPts - 1], aNewId);
229 theOutput->SetPoints(newPts);
236 theOutput->Squeeze();
240 return aRegionSizes->GetMaxId() + 1;
244 // Mark current cell as visited and assign region number. Note:
245 // traversal occurs across shared vertices.
247 void VISU_LabelPointsFilter::TraverseAndMark (vtkIdList* theWave,
250 vtkIdType* thePointMap,
251 int& theRegionNumber,
252 vtkIdType& thePointNumber,
253 vtkPolyData* theMesh)
255 vtkIdType cellId, ptId, numIds, i;
257 vtkIdType *pts, *cells, npts;
259 unsigned short ncells;
260 vtkIdList* aNeighborCellPointIds = vtkIdList::New();
263 while ( (numIds=theWave->GetNumberOfIds()) > 0 ) {
264 for ( i=0; i < numIds; i++ ) {
265 cellId = theWave->GetId(i);
266 if ( theVisited[cellId] < 0 ) {
267 theVisited[cellId] = theRegionNumber;
268 theMesh->GetCellPoints(cellId, npts, pts);
270 for (j=0; j < npts; j++) {
271 if ( thePointMap[ptId=pts[j]] < 0 ) {
272 thePointMap[ptId] = thePointNumber++;
274 theMesh->GetPointCells(ptId,ncells,cells);
276 // check connectivity criterion (geometric + scalar)
277 for (k=0; k < ncells; k++) {
279 theWave2->InsertNextId(cellId);
281 }//for all cells using this point
282 }//for all points of this cell
283 }//if cell not yet visited
284 }//for all cells in this wave
290 } //while wave is not empty