2 // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
4 #include "bbcreaVtkCleanMeshWithPatch.h"
5 #include "bbcreaVtkPackage.h"
7 #include <vtkAppendPolyData.h>
8 #include <vtkStaticPointLocator.h>
9 #include <vtkDijkstraGraphGeodesicPath.h>
10 #include <vtkIdList.h>
11 #include <vtkCharArray.h>
12 #include <vtkPolyDataConnectivityFilter.h>
13 #include <vtkPointData.h>
14 #include <vtkCellData.h>
15 #include <vtkFillHolesFilter.h>
16 #include <vtkPolyDataNormals.h>
17 #include <vtkIdFilter.h>
18 #include <vtkFeatureEdges.h>
19 #include <vtkCleanPolyData.h>
20 #include <vtkTriangleFilter.h>
21 #include <vtkStripper.h>
22 #include <vtkTriangleStrip.h>
23 #include <vtkRuledSurfaceFilter.h>
27 // #include <vtkImprintFilter.h>
33 BBTK_ADD_BLACK_BOX_TO_PACKAGE(creaVtk,CleanMeshWithPatch)
34 BBTK_BLACK_BOX_IMPLEMENTATION(CleanMeshWithPatch,bbtk::AtomicBlackBox);
36 // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
38 void CleanMeshWithPatch::Process()
40 // THE MAIN PROCESSING METHOD BODY
41 // Here we simply set the input 'In' value to the output 'Out'
42 // And print out the output value
43 // INPUT/OUTPUT ACCESSORS ARE OF THE FORM :
44 // void bbSet{Input|Output}NAME(const TYPE&)
45 // const TYPE& bbGet{Input|Output}NAME() const
47 // * NAME is the name of the input/output
48 // (the one provided in the attribute 'name' of the tag 'input')
49 // * TYPE is the C++ type of the input/output
50 // (the one provided in the attribute 'type' of the tag 'input')
51 // bbSetOutputOut( bbGetInputIn() );
52 // std::cout << "Output value = " <<bbGetOutputOut() << std::endl;
54 std::vector<int> lstIndexs = bbGetInputLstIndexs();
55 if (( lstIndexs.size()>=3 ) && (bbGetInputMesh()!=NULL) ) {
58 // Step 1. ----Get perimeter CtrlPoints-----
59 std::vector<double> lstX = bbGetInputLstX();
60 std::vector<double> lstY = bbGetInputLstY();
61 std::vector<double> lstZ = bbGetInputLstZ();
62 std::vector<double> perimeterX;
63 std::vector<double> perimeterY;
64 std::vector<double> perimeterZ;
65 std::vector<double> tmpX;
66 std::vector<double> tmpY;
67 std::vector<double> tmpZ;
68 int iGroup,sizeGroups = lstIndexs.size();
69 int i,iGeneral=0,size;
70 for (iGroup=0 ; iGroup<sizeGroups ; iGroup++)
74 for (i=iGeneral ; i<iGeneral+lstIndexs[iGroup] ; i++)
76 perimeterX.push_back( lstX[i] );
77 perimeterY.push_back( lstY[i] );
78 perimeterZ.push_back( lstZ[i] );
81 if ((iGroup!=0) && (iGroup!=sizeGroups-1))
83 i=iGeneral+(lstIndexs[iGroup]-1);
84 perimeterX.push_back( lstX[i] );
85 perimeterY.push_back( lstY[i] );
86 perimeterZ.push_back( lstZ[i] );
87 tmpX.insert( tmpX.begin() , lstX[iGeneral] );
88 tmpY.insert( tmpY.begin() , lstY[iGeneral] );
89 tmpZ.insert( tmpZ.begin() , lstZ[iGeneral] );
91 if (iGroup==sizeGroups-1)
93 for (i=iGeneral+lstIndexs[iGroup]-1 ; i>=iGeneral ; i--)
95 perimeterX.push_back( lstX[i] );
96 perimeterY.push_back( lstY[i] );
97 perimeterZ.push_back( lstZ[i] );
100 iGeneral=iGeneral+lstIndexs[iGroup];
103 for (i=0; i<size ; i++)
105 perimeterX.push_back( tmpX[i] );
106 perimeterY.push_back( tmpY[i] );
107 perimeterZ.push_back( tmpZ[i] );
109 // Step 2. ----Get Ids in Mesh of perimeter CtrlPoints-----
110 std::vector<double> spc;
111 if (bbGetInputSpacing().size()<3)
117 spc = bbGetInputSpacing();
119 vtkStaticPointLocator *pointLocator;
120 pointLocator = vtkStaticPointLocator::New();
121 pointLocator->SetDataSet( bbGetInputMesh() );
122 pointLocator->BuildLocator();
124 size=perimeterX.size();
125 std::vector<long int> lstIdsCtrlPoints;
128 id = pointLocator->FindClosestPoint( perimeterX[i]*spc[0] ,perimeterY[i]*spc[1] , perimeterZ[i]*spc[2] ) ;
129 lstIdsCtrlPoints.push_back( id );
131 // Step 3 Get geodesic path from segments
133 std::vector<long int> lstIdsGeodesicPerimter;
134 vtkAppendPolyData* append = vtkAppendPolyData::New();
137 id1=lstIdsCtrlPoints[i];
140 id2 = lstIdsCtrlPoints[i+1];
142 id2 = lstIdsCtrlPoints[0];
144 vtkDijkstraGraphGeodesicPath *pathFilter = vtkDijkstraGraphGeodesicPath::New();
145 pathFilter->SetInputData( bbGetInputMesh() );
146 pathFilter->SetStartVertex( id1 );
147 pathFilter->SetEndVertex( id2 );
148 pathFilter->Update();
149 append->AddInputData( pathFilter->GetOutput() );
152 // Step 3.1 Puts ids of perimeter Subsegment in vector lstIdsGeodesicPerimter
153 vtkIdList *IdsList = pathFilter->GetIdList();
154 long int iIdLst,sizeIdLst = IdsList->GetNumberOfIds();
155 for (iIdLst=0; iIdLst<sizeIdLst; iIdLst++)
157 lstIdsGeodesicPerimter.push_back( IdsList->GetId(iIdLst) );
160 pathFilter->Delete();
163 // bbSetOutputOut( append->GetOutput() );
165 // Step 4. -- Define scalars ---
166 vtkCharArray *scalarsArray = vtkCharArray::New();
167 vtkPoints *points = bbGetInputMesh()->GetPoints();
168 long int iMPs,sizeMPs = points->GetNumberOfPoints();
169 scalarsArray->SetNumberOfValues(sizeMPs);
170 for (iMPs=0; iMPs<sizeMPs; iMPs++)
172 scalarsArray->SetValue(iMPs,15);
174 long int iIdLst,sizeIdLst = lstIdsGeodesicPerimter.size();
175 for (iIdLst=0; iIdLst<sizeIdLst; iIdLst++)
177 scalarsArray->SetValue( lstIdsGeodesicPerimter[iIdLst] ,100 );
179 scalarsArray->SetName("scalarsPerimeterPatch");
180 bbGetInputMesh()->GetPointData()->AddArray( scalarsArray );
181 bbGetInputMesh()->GetPointData()->SetActiveScalars( "scalarsPerimeterPatch" );
182 bbGetInputMesh()->GetCellData()->SetActiveScalars( "scalarsPerimeterPatch" );
184 // Step 5. -- Connectivity Filter
185 vtkPolyDataConnectivityFilter *connectivity = vtkPolyDataConnectivityFilter::New();
186 connectivity->SetInputData( bbGetInputMesh() );
187 connectivity->SetScalarConnectivity(true);
189 // just perimeter mesh
190 // connectivity->SetExtractionModeToPointSeededRegions();
191 // connectivity->InitializeSeedList();
192 // connectivity->AddSeed( lstIdsGeodesicPerimter[0] );
193 // connectivity->SetScalarRange(90,110);
194 // connectivity->SetFullScalarConnectivity(false);
196 //connectivity->SetExtractionModeToCellSeededRegions();
197 //connectivity->InitializeSeedList();
198 //connectivity->AddSeed(0);
199 //connectivity->SetScalarRange(10,20);
200 //connectivity->SetFullScalarConnectivity(true);
202 //connectivity->SetExtractionModeToPointSeededRegions();
203 //connectivity->InitializeSeedList();
204 //connectivity->AddSeed(0);
205 //connectivity->SetScalarRange(10,20);
206 //connectivity->SetFullScalarConnectivity(true);
210 connectivity->SetExtractionModeToLargestRegion();
211 connectivity->SetScalarRange(10,20);
212 connectivity->SetFullScalarConnectivity(true);
215 connectivity->Update();
216 // bbSetOutputOut( connectivity->GetOutput() );
218 // printf("EED CleanMeshWithPatch::Process connectivity GetNumberOfPoints %ld \n ", connectivity->GetOutput()->GetNumberOfPoints() );
221 vtkAppendPolyData* append3 = vtkAppendPolyData::New();
222 append3->AddInputData( connectivity->GetOutput() );
223 append3->AddInputData( bbGetInputPatch() );
226 vtkStripper *stripper = vtkStripper::New();
227 stripper->SetInputData( append3->GetOutput() );
229 bbSetOutputOut( stripper->GetOutput() );
233 vtkFeatureEdges *edges1 = vtkFeatureEdges::New();
234 edges1->SetInputData( connectivity->GetOutput() );
235 edges1->BoundaryEdgesOn();
236 edges1->ManifoldEdgesOff();
237 edges1->NonManifoldEdgesOff();
238 edges1->FeatureEdgesOff();
240 // bbSetOutputOut( edges1->GetOutput() );
242 vtkFeatureEdges *edges2 = vtkFeatureEdges::New();
243 edges2->SetInputData( bbGetInputPatch() );
244 edges2->BoundaryEdgesOn();
245 edges2->ManifoldEdgesOff();
246 edges2->NonManifoldEdgesOff();
247 edges2->FeatureEdgesOff();
249 // bbSetOutputOut( edges1->GetOutput() );
251 vtkAppendPolyData* append3 = vtkAppendPolyData::New();
252 append3->AddInputData( edges1->GetOutput() );
253 append3->AddInputData( edges2->GetOutput() );
255 // bbSetOutputOut( append3->GetOutput() );
256 vtkRuledSurfaceFilter *ruledSurfaceFilter = vtkRuledSurfaceFilter::New();
257 ruledSurfaceFilter->SetInputData( append3->GetOutput() );
258 ruledSurfaceFilter->Update();
259 bbSetOutputOut( ruledSurfaceFilter->GetOutput() );
265 // bbSetOutputOut( connectivity->GetOutput() );
268 vtkCleanPolyData *connectivityClean = vtkCleanPolyData::New();
269 connectivityClean->SetInputData( connectivity->GetOutput() );
270 connectivityClean->Update();
272 //step 6.2. -- connect both meshes ConnectivityClean->Patch --
273 Stretch( bbGetInputPatch(), connectivityClean->GetOutput() );
274 //step 6.1. -- connect both meshes Patch->ConnectivityClean --
275 Stretch( connectivityClean->GetOutput() , bbGetInputPatch() );
278 //step 6.1. -- connect both meshes Patch->ConnectivityClean --
279 vtkIdFilter *idFilter = vtkIdFilter::New();
280 idFilter->SetInputData( bbGetInputPatch() );
281 //idFilter->SetIdsArrayName("ids");
282 //idFilter->SetCellIdsArrayName("ids");
283 idFilter->SetPointIdsArrayName("ids");
284 idFilter->SetPointIds(true);
285 idFilter->SetCellIds(false);
286 //# Available for vtk>=8.3:
287 // #idFilter.SetPointIdsArrayName(arrayName)
288 // #idFilter.SetCellIdsArrayName(arrayName)
290 vtkFeatureEdges *edges = vtkFeatureEdges::New();
291 edges->SetInputData( idFilter->GetOutput() );
292 edges->BoundaryEdgesOn();
293 edges->ManifoldEdgesOff();
294 edges->NonManifoldEdgesOff();
295 edges->FeatureEdgesOff();
297 vtkIdTypeArray* arrayIds = vtkIdTypeArray::SafeDownCast(edges->GetOutput()->GetPointData()->GetArray("ids"));
298 long int iIds,sizeArrayIds = edges->GetOutput()->GetNumberOfPoints();
299 printf("\n EED CleanMeshWithPatch::Process sizeArrayIds=%ld \n", sizeArrayIds);
302 vtkPolyData *newMesh = connectivityClean->GetOutput();
303 vtkStaticPointLocator *pointLocator2 = vtkStaticPointLocator::New();
304 pointLocator2->SetDataSet( newMesh );
305 pointLocator2->BuildLocator();
306 vtkPoints *pointsPatch = bbGetInputPatch()->GetPoints();
307 vtkPoints *pointsNewMesh = newMesh->GetPoints();
308 double pP[3], pPP[3];
310 for (iIds=0; iIds<sizeArrayIds ; iIds++ )
312 pointsPatch->GetPoint( arrayIds->GetValue(iIds) , pP );
313 idNewMesh = pointLocator2->FindClosestPoint(pP);
314 pointsNewMesh->GetPoint( idNewMesh , pPP );
315 pointsPatch->SetPoint( arrayIds->GetValue(iIds) , pPP );
316 printf(" iIds=%ld pP=%f %f %f idNewMesh=%ld pPP=%f %f %f \n", arrayIds->GetValue(iIds) , pP[0], pP[1], pP[2], idNewMesh, pPP[0], pPP[1], pPP[2] );
318 bbGetInputPatch()->Modified();
320 //step 6.2. -- connect both meshes ConnectivityClean->Patch --
321 vtkIdFilter *idFilter2 = vtkIdFilter::New();
322 idFilter2->SetInputData( newMesh );
323 //idFilter->SetIdsArrayName("ids");
324 //idFilter->SetCellIdsArrayName("ids");
325 idFilter2->SetPointIdsArrayName("ids");
326 idFilter2->SetPointIds(true);
327 idFilter2->SetCellIds(false);
328 //# Available for vtk>=8.3:
329 // #idFilter.SetPointIdsArrayName(arrayName)
330 // #idFilter.SetCellIdsArrayName(arrayName)
332 vtkFeatureEdges *edges2 = vtkFeatureEdges::New();
333 edges2->SetInputData( idFilter2->GetOutput() );
334 edges2->BoundaryEdgesOn();
335 edges2->ManifoldEdgesOff();
336 edges2->NonManifoldEdgesOff();
337 edges2->FeatureEdgesOff();
339 vtkIdTypeArray* arrayIds2 = vtkIdTypeArray::SafeDownCast(edges2->GetOutput()->GetPointData()->GetArray("ids"));
340 long int iIds2,sizeArrayIds2 = edges2->GetOutput()->GetNumberOfPoints();
341 printf("\n EED CleanMeshWithPatch::Process sizeArrayIds2=%ld \n", sizeArrayIds2);
342 // vtkPolyData *newMesh = connectivityClean->GetOutput();
343 vtkStaticPointLocator *pointLocator3 = vtkStaticPointLocator::New();
344 pointLocator3->SetDataSet( bbGetInputPatch() );
345 pointLocator3->BuildLocator();
346 vtkPoints *pointsNewMesh2 = newMesh->GetPoints();
347 vtkPoints *pointsPatch2 = bbGetInputPatch()->GetPoints();
348 double pP2[3], pPP2[3];
350 for (iIds2=0; iIds2<sizeArrayIds2 ; iIds2++ )
352 pointsNewMesh2->GetPoint( arrayIds2->GetValue(iIds2) , pP2 );
353 idPatch = pointLocator3->FindClosestPoint(pP2);
354 pointsPatch2->GetPoint( idPatch , pPP2 );
355 pointsNewMesh2->SetPoint( arrayIds2->GetValue(iIds) , pPP2 );
356 printf(" iIds=%ld pP=%f %f %f idNewMesh=%ld pPP=%f %f %f \n", arrayIds2->GetValue(iIds) , pP2[0], pP2[1], pP2[2], idPatch, pPP2[0], pPP2[1], pPP2[2] );
362 // step 7. -- Append meshes--
363 vtkAppendPolyData* append2 = vtkAppendPolyData::New();
364 append2->AddInputData( connectivityClean->GetOutput() );
365 append2->AddInputData( bbGetInputPatch() );
368 vtkCleanPolyData *append2Clean = vtkCleanPolyData::New();
369 append2Clean->SetInputData( append2->GetOutput() );
370 append2Clean->Update();
372 vtkTriangleFilter *triangles = vtkTriangleFilter::New();
373 triangles->SetInputData( append2Clean->GetOutput() );
375 // bbSetOutputOut( triangles->GetOutput() );
377 //step 8. -- Clean --
379 vtkPolyDataNormals *normals =vtkPolyDataNormals::New();
380 normals->SetInputConnection( triangles->GetOutputPort() );
381 normals->SetInputConnection( append2Clean->GetOutputPort() );
382 normals->ConsistencyOn();
383 normals->SplittingOff();
385 // bbSetOutputOut( normals->GetOutput() );
387 vtkFillHolesFilter *fillHoles = vtkFillHolesFilter::New();
388 fillHoles->SetInputData( normals->GetOutput() );
389 fillHoles->SetHoleSize(1000);
391 bbSetOutputOut( fillHoles->GetOutput() );
395 // Step 4. -- vtkImprintFilter ---
396 vtkImprintFilter *imp = vtkImprintFilter::New();
397 // imp->SetTargetData( append->GetOutput() );
398 // imp->SetImprintData( bbGetInputMesh() );
400 // imp->SetTargetData( bbGetInputMesh() );
401 // imp->SetImprintData( append->GetOutput() );
403 // imp->SetTargetData( bbGetInputMesh() );
404 // imp->SetImprintData( bbGetInputPatch() );
406 imp->SetTargetData( bbGetInputMesh() );
407 imp->SetImprintData( bbGetInputPatch() );
409 // imp->SetOutputTypeToProjectedImprint();
410 imp->SetOutputTypeToTargetCells();
411 // imp->SetOutputTypeToImprintedCells();
412 // imp->SetOutputTypeToImprintedRegion();
413 // imp->SetOutputTypeToMergedImprint();
415 imp->SetTolerance(500);
417 bbSetOutputOut( imp->GetOutput() );
421 bbSetOutputOut( NULL );
422 } // if LstIndexs size >=3
428 void CleanMeshWithPatch::Stretch(vtkPolyData *newMesh, vtkPolyData *patchMesh)
431 vtkIdFilter *idFilter = vtkIdFilter::New();
432 idFilter->SetInputData( patchMesh );
433 //idFilter->SetIdsArrayName("ids");
434 //idFilter->SetCellIdsArrayName("ids");
435 idFilter->SetPointIdsArrayName("ids");
436 idFilter->SetPointIds(true);
437 idFilter->SetCellIds(false);
438 //# Available for vtk>=8.3:
439 // #idFilter.SetPointIdsArrayName(arrayName)
440 // #idFilter.SetCellIdsArrayName(arrayName)
442 vtkFeatureEdges *edges = vtkFeatureEdges::New();
443 edges->SetInputData( idFilter->GetOutput() );
444 edges->BoundaryEdgesOn();
445 edges->ManifoldEdgesOff();
446 edges->NonManifoldEdgesOff();
447 edges->FeatureEdgesOff();
449 vtkIdTypeArray* arrayIds = vtkIdTypeArray::SafeDownCast(edges->GetOutput()->GetPointData()->GetArray("ids"));
450 long int iIds,sizeArrayIds = edges->GetOutput()->GetNumberOfPoints();
454 vtkIdFilter *idFilter2 = vtkIdFilter::New();
455 idFilter2->SetInputData( newMesh );
456 //idFilter2->SetIdsArrayName("ids");
457 //idFilter2->SetCellIdsArrayName("ids");
458 idFilter2->SetPointIdsArrayName("ids");
459 idFilter2->SetPointIds(true);
460 idFilter2->SetCellIds(false);
461 //# Available for vtk>=8.3:
462 // #idFilter2.SetPointIdsArrayName(arrayName)
463 // #idFilter2.SetCellIdsArrayName(arrayName)
465 vtkFeatureEdges *edges2 = vtkFeatureEdges::New();
466 edges2->SetInputData( idFilter2->GetOutput() );
467 edges2->BoundaryEdgesOn();
468 edges2->ManifoldEdgesOff();
469 edges2->NonManifoldEdgesOff();
470 edges2->FeatureEdgesOff();
472 vtkIdTypeArray* arrayIds2 = vtkIdTypeArray::SafeDownCast(edges2->GetOutput()->GetPointData()->GetArray("ids"));
473 long int iIds2,sizeArrayIds2 = edges2->GetOutput()->GetNumberOfPoints();
478 vtkStaticPointLocator *pointLocator2 = vtkStaticPointLocator::New();
479 //EED2 pointLocator2->SetDataSet( newMesh );
480 pointLocator2->SetDataSet( edges2->GetOutput() );
482 pointLocator2->BuildLocator();
483 vtkPoints *pointsPatch = patchMesh->GetPoints();
484 vtkPoints *pointsNewMesh = newMesh->GetPoints();
485 double pP[3], pPP[3];
487 for (iIds=0; iIds<sizeArrayIds ; iIds++ )
489 pointsPatch->GetPoint( arrayIds->GetValue(iIds) , pP );
491 //EED2 idNewMesh = pointLocator2->FindClosestPoint(pP);
492 iIds2 = pointLocator2->FindClosestPoint(pP);
493 idNewMesh = arrayIds2->GetValue(iIds2);
495 pointsNewMesh->GetPoint( idNewMesh , pPP );
496 pointsPatch->SetPoint( arrayIds->GetValue(iIds) , pPP );
498 patchMesh->Modified();
504 // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
506 void CleanMeshWithPatch::bbUserSetDefaultValues()
508 // SET HERE THE DEFAULT INPUT/OUTPUT VALUES OF YOUR BOX
509 // Here we initialize the input 'In' to 0
510 bbSetInputMesh(NULL);
511 bbSetInputPatch(NULL);
512 bbSetOutputOut(NULL);
516 // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
518 void CleanMeshWithPatch::bbUserInitializeProcessing()
520 // THE INITIALIZATION METHOD BODY :
522 // but this is where you should allocate the internal/output pointers
527 // Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
529 void CleanMeshWithPatch::bbUserFinalizeProcessing()
531 // THE FINALIZATION METHOD BODY :
533 // but this is where you should desallocate the internal/output pointers
537 } // EO namespace bbcreaVtk