]> Creatis software - creaMaracasVisu.git/blob - bbtk/src/bbcreaMaracasVisuShowNPoints_Tools.cxx
#3518 ShowNPoints propose new points in new Collection (group)
[creaMaracasVisu.git] / bbtk / src / bbcreaMaracasVisuShowNPoints_Tools.cxx
1 //===== 
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)
3 //===== 
4 #include "bbcreaMaracasVisuShowNPoints_Tools.h"
5 #include "bbcreaMaracasVisuPackage.h"
6
7 #include <vtkPointData.h>
8 #include <vtkDataArray.h>
9 #include <vtkMath.h>
10
11
12 namespace bbcreaMaracasVisu
13 {
14
15 BBTK_ADD_BLACK_BOX_TO_PACKAGE(creaMaracasVisu,ShowNPoints_Tools)
16 BBTK_BLACK_BOX_IMPLEMENTATION(ShowNPoints_Tools,bbtk::AtomicBlackBox);
17
18
19
20 void ShowNPoints_Tools::NearestPointToMesh( vtkPoints *points,vtkStaticPointLocator *pointLocator,double *spc,double *p,double *pM)
21 {
22     p[0]  = p[0] * spc[0];
23     p[1]  = p[1] * spc[1];
24     p[2]  = p[2] * spc[2];
25     points->GetPoint( pointLocator->FindClosestPoint(p) , pM );
26     pM[0] = pM[0] / spc[0];
27     pM[1] = pM[1] / spc[1];
28     pM[2] = pM[2] / spc[2];
29 }
30
31 void ShowNPoints_Tools::CreatePatch_3points()
32 {
33         //printf("PG ShowNPoints_Tools::CreatePatch_3points  Entered patch 3 points !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
34         WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
35         
36         std::vector<double> lstX = wsp->GetModelShowNPoints()->GetLstPointsX();
37         std::vector<double> lstY = wsp->GetModelShowNPoints()->GetLstPointsY();
38         std::vector<double> lstZ = wsp->GetModelShowNPoints()->GetLstPointsZ();
39         
40         double pA[3];
41     pA[0] = lstX[0];
42     pA[1] = lstY[0];
43     pA[2] = lstZ[0];
44     double pB[3];
45     pB[0] = lstX[1];
46     pB[1] = lstY[1];
47     pB[2] = lstZ[1];
48     double pC[3];
49     pC[0] = lstX[2];
50     pC[1] = lstY[2];
51     pC[2] = lstZ[2];
52
53         double v[3];
54         double u[3];
55         vtkMath::Subtract(pC,pA,v);
56         vtkMath::Subtract(pB,pA,u);
57         
58         /**point in AC closest to B.
59         *formula t=(V)dot(U)/(V)dot(V)
60         */
61         double t = vtkMath::Dot(v,u)/vtkMath::Dot(v,v);
62         /**nP found point
63         *formula A+t(C-A) -> A+tV
64         */
65         vtkMath::MultiplyScalar(v, t);
66         double nP[3];
67         vtkMath::Add(pA, v, nP);
68         
69         //calculate direction vector from found point to B
70         double dirVector[3];
71         vtkMath::Subtract(pB, nP, dirVector);
72         
73         double pointAdd[3];
74         double pointSub[3];
75         
76         //Add and subtract direction vector to A and C to find the 4 points to create the patch,
77         
78         std::vector<double> resListX;
79         std::vector<double> resListY;
80         std::vector<double> resListZ;
81         
82         vtkMath::Add(pA, dirVector, pointAdd);
83         vtkMath::Subtract(pA, dirVector, pointSub);
84         
85         resListX.push_back(pointSub[0]);
86         resListY.push_back(pointSub[1]);
87         resListZ.push_back(pointSub[2]);
88
89         resListX.push_back(pointAdd[0]);
90         resListY.push_back(pointAdd[1]);
91         resListZ.push_back(pointAdd[2]);
92         
93         
94         vtkMath::Add(pC, dirVector, pointAdd);
95         vtkMath::Subtract(pC, dirVector, pointSub);
96         
97         resListX.push_back(pointAdd[0]);
98         resListY.push_back(pointAdd[1]);
99         resListZ.push_back(pointAdd[2]);
100         
101         resListX.push_back(pointSub[0]);
102         resListY.push_back(pointSub[1]);
103         resListZ.push_back(pointSub[2]);
104
105         //Create patch given the previously calculated points (4 points)
106         CreatePatch_Points(resListX, resListY, resListZ);
107 }
108
109 void ShowNPoints_Tools::CreatePatch_4points()
110 {
111         WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
112              
113         std::vector<double> lstX = wsp->GetModelShowNPoints()->GetLstPointsX();
114         std::vector<double> lstY = wsp->GetModelShowNPoints()->GetLstPointsY();
115         std::vector<double> lstZ = wsp->GetModelShowNPoints()->GetLstPointsZ();
116         CreatePatch_Points(lstX, lstY, lstZ);
117 }
118
119 void ShowNPoints_Tools::InitCreatePatch_Points()
120 {
121         WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
122         wsp->StopAutoAddPoints();
123     wsp->StopTrackPoint();
124         if((wsp->GetLstModelShowNPointsSize()==1) && (bbGetInputMesh()!=NULL ))
125     {
126                 if(wsp->GetModelShowNPoints()->GetLstPointsSize()==4){
127                         CreatePatch_4points();
128                 }
129                 else if(wsp->GetModelShowNPoints()->GetLstPointsSize()==3){
130                         CreatePatch_3points();
131                 }
132                 else{
133                         printf("PG ShowNPoints_Tools::CreatePatch_Npoints  Warning patch not apply. Number of points is invalid. Group should have 3 or 4 points\n");
134                 }
135         }
136         else{
137                 printf("PG ShowNPoints_Tools::CreatePatch_Npoints  Warning patch not apply. groups or mesh invalid. Need 1 group of 3 or 4 points, and a mesh\n");
138     } // if wsp && mesh
139 }
140
141 void ShowNPoints_Tools::InitCreateVolumeSurface_Points()
142 {
143     InitCreatePatch_Points();   //  1 group -> 3 groups
144     
145     // 3 groups to 4 groups
146     WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
147     wsp->StopAutoAddPoints();
148     wsp->StopTrackPoint();
149     if( wsp->GetLstModelShowNPointsSize()==3 )
150     {
151         double spc[3];
152         double pC1[3];    // fist point
153         double dx,dy,dz;
154         double pC2A[3];  // first middle point
155         double pC2B[3];  // second midle point
156         double pC3[3];   // last point
157         double pN[3];    // new over the surface
158
159         vtkPoints               *points         = bbGetInputMesh()->GetPoints();
160         vtkStaticPointLocator   *pointLocator   = vtkStaticPointLocator::New();
161         pointLocator->SetDataSet( bbGetInputMesh() );
162         pointLocator->BuildLocator();
163         spc[0]          = bbGetInputSpacing()[0];
164         spc[1]          = bbGetInputSpacing()[1];
165         spc[2]          = bbGetInputSpacing()[2];
166         wsp->InsertCollectionAfter_();
167         wsp->GetCollectionPoint(1,0, pC1);
168         wsp->GetCollectionPoint(1,2, pC3);
169         dx=pC3[0]-pC1[0];
170         dy=pC3[1]-pC1[1];
171         dz=pC3[2]-pC1[2];
172         pC2A[0]=pC1[0]+dx*0.33333;   pC2A[1]=pC1[1]+dy*0.3333;   pC2A[2]=pC1[2]+dz*0.33333;
173         pC2B[0]=pC1[0]+dx*0.66666;   pC2B[1]=pC1[1]+dy*0.6666;   pC2B[2]=pC1[2]+dz*0.66666;
174         
175         wsp->InsertPoint(pC1[0] ,pC1[1], pC1[2],"");
176         
177         NearestPointToMesh(points, pointLocator, spc, pC2A,pN);
178         wsp->InsertPoint(pN[0] ,pN[1], pN[2],"");
179         
180         NearestPointToMesh(points, pointLocator, spc, pC2B,pN);
181         wsp->InsertPoint(pN[0] ,pN[1], pN[2],"");
182         
183         wsp->InsertPoint(pC3[0] ,pC3[1], pC3[2],"");
184         
185         
186         // Add points to the other Groups
187         std::vector<double> pointStart;
188         pointStart.push_back( pC1[0] );
189         pointStart.push_back( pC1[1] );
190         pointStart.push_back( pC1[2] );
191         std::vector<double> pointEnd;
192         pointEnd.push_back( pC3[0] );
193         pointEnd.push_back( pC3[1] );
194         pointEnd.push_back( pC3[2] );
195
196         wsp->SetActualCollection(0);
197         wsp->SetReferencePoint(pointStart);
198         wsp->OnInsertPoint_();
199         wsp->SetReferencePoint(pointEnd);
200         wsp->OnInsertPoint_();
201
202         wsp->SetActualCollection(2);
203         wsp->SetReferencePoint(pointStart);
204         wsp->OnInsertPoint_();
205         wsp->SetReferencePoint(pointEnd);
206         wsp->OnInsertPoint_();
207
208         // --- Finish ---
209         wsp->SetOutputBox();
210         wsp->UndoRedo_SaveCollection();
211
212     } // if wsp && mesh
213 }
214
215
216 void ShowNPoints_Tools::CreatePatch_Points(std::vector<double> lstX, std::vector<double> lstY, std::vector<double> lstZ)
217 {
218     WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
219     std::vector<long int>   lstIdNormalSurface;
220     double                  spc[3];
221                             spc[0]          = bbGetInputSpacing()[0];
222                             spc[1]          = bbGetInputSpacing()[1];
223                             spc[2]          = bbGetInputSpacing()[2];
224     vtkPoints               *points         = bbGetInputMesh()->GetPoints();
225     vtkStaticPointLocator   *pointLocator   = vtkStaticPointLocator::New();
226     pointLocator->SetDataSet( bbGetInputMesh() );
227     pointLocator->BuildLocator();
228     wsp->StopTrackPoint();
229     double p[3],pM[3];
230     double dx,dy,dz;
231     
232     wsp->DeleteAllPoints_();
233     //wsp->ErasePoint( 0 );
234     //wsp->ErasePoint( 0 );
235     //wsp->ErasePoint( 0 );
236     //wsp->ErasePoint( 0 );
237     // --- Group 0 ---
238     dx = lstX[1]-lstX[0];
239     dy = lstY[1]-lstY[0];
240     dz = lstZ[1]-lstZ[0];
241     //
242     //
243     double part = 0.25;
244     for(int sect = 0; sect < 5; sect++)
245     {
246         p[0] = lstX[0] + dx*(sect*part);
247                 p[1] = lstY[0] + dy*(sect*part);
248                 p[2] = lstZ[0] + dz*(sect*part);
249                 if(sect == 4){
250                         p[0] = p[0] + 0.5*(((lstX[1]+lstX[2])/2)-p[0]);
251                         p[1] = p[1] + 0.5*(((lstY[1]+lstY[2])/2)-p[1]);
252                         p[2] = p[2] + 0.5*(((lstZ[1]+lstZ[2])/2)-p[2]);
253                 }
254                 if(sect == 0){
255                         p[0] = p[0] + 0.5*(((lstX[0]+lstX[3])/2)-p[0]);
256                         p[1] = p[1] + 0.5*(((lstY[0]+lstY[3])/2)-p[1]);
257                         p[2] = p[2] + 0.5*(((lstZ[0]+lstZ[3])/2)-p[2]);
258                 }
259                 NearestPointToMesh(points, pointLocator, spc, p,pM);
260                 wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
261                 if(sect == 0 || sect == 4) lstIdNormalSurface.push_back( pointLocator->FindClosestPoint(pM) );
262     }
263         
264     // --- Group 1 ---
265     double centroid[3];
266     
267     wsp->InsertCollectionAfter_();
268       p[0] = (lstX[0]+lstX[3])/2;
269       p[1] = (lstY[0]+lstY[3])/2;
270       p[2] = (lstZ[0]+lstZ[3])/2;
271       NearestPointToMesh(points, pointLocator, spc, p,pM);
272       wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
273       p[0] = (lstX[1]+lstX[2])/2;
274       p[1] = (lstY[1]+lstY[2])/2;
275       p[2] = (lstZ[1]+lstZ[2])/2;
276       NearestPointToMesh(points, pointLocator, spc, p,pM);
277       wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
278       p[0] = (lstX[0]+lstX[1]+lstX[2]+lstX[3])/4;          p[1] = (lstY[0]+lstY[1]+lstY[2]+lstY[3])/4;          p[2] = (lstZ[0]+lstZ[1]+lstZ[2]+lstZ[3])/4;
279       wsp->InsertPoint(p[0] ,p[1], p[2],"");
280           std::copy(std::begin(p), std::end(p), std::begin(centroid));
281     // --- Group 2 ---
282     wsp->InsertCollectionAfter_();
283     dx = lstX[2]-lstX[3];
284     dy = lstY[2]-lstY[3];
285     dz = lstZ[2]-lstZ[3];  
286     for(int sect = 0; sect < 5; sect++)
287     {
288         p[0] = lstX[3] + dx*(sect*part);
289                 p[1] = lstY[3] + dy*(sect*part);
290                 p[2] = lstZ[3] + dz*(sect*part);
291                 if(sect == 4){
292                         p[0] = p[0] + 0.5*(((lstX[1]+lstX[2])/2)-p[0]);
293                         p[1] = p[1] + 0.5*(((lstY[1]+lstY[2])/2)-p[1]);
294                         p[2] = p[2] + 0.5*(((lstZ[1]+lstZ[2])/2)-p[2]);
295                 }
296                 if(sect == 0){
297                         p[0] = p[0] + 0.5*(((lstX[0]+lstX[3])/2)-p[0]);
298                         p[1] = p[1] + 0.5*(((lstY[0]+lstY[3])/2)-p[1]);
299                         p[2] = p[2] + 0.5*(((lstZ[0]+lstZ[3])/2)-p[2]);
300                 }
301                 NearestPointToMesh(points, pointLocator, spc, p,pM);
302                 wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
303                 if(sect == 0 || sect == 4) lstIdNormalSurface.push_back( pointLocator->FindClosestPoint(pM) );
304     }
305      pointLocator->Delete();
306     // Check normals
307 //        1. Recorrer las normales de lstIdNormals y calcular el promedio  -> V1
308     double          *nValue;
309         double                  n1[3];
310     vtkPointData    *pointdata  =  bbGetInputMesh()->GetPointData();
311     vtkDataArray    *dataarray  = pointdata->GetNormals();
312         int i,size = lstIdNormalSurface.size();
313         n1[0]=0;
314         n1[1]=0;
315         n1[2]=0;
316         for (i=0; i<size; i++)
317         {
318             nValue        = dataarray->GetTuple3( lstIdNormalSurface[i] );
319                 n1[0] = n1[0] + nValue[0];
320                 n1[1] = n1[1] + nValue[1];
321                 n1[2] = n1[2] + nValue[2];
322         } // for i
323         n1[0] = n1[0]/size;
324         n1[1] = n1[1]/size;
325         n1[2] = n1[2]/size;
326
327 //        2. Calcular el promedio de 4 normales de la nueva superficie     -> V2
328     double pC[3];
329     double pM1[3];
330     double pM2[3];
331     double n2[3];
332     n2[0] = 0;
333     n2[1] = 0;
334     n2[2] = 0;
335     // Collection 0 with 4 points
336     // Collection 1 with 3 points
337     // Collection 2 with 4 points
338     wsp->GetCollectionPoint(1,1, pC);
339     
340     wsp->GetCollectionPoint(0,0, pM);
341     vtkMath::Subtract(pM,pC,pM1);
342     wsp->GetCollectionPoint(0,3, pM);
343     vtkMath::Subtract(pM,pC,pM2);
344     vtkMath::Cross(pM1,pM2,pM);
345     n2[0] = pM[0];
346     n2[1] = pM[1];
347     n2[2] = pM[2];
348
349     wsp->GetCollectionPoint(0,3, pM);
350     vtkMath::Subtract(pM,pC,pM1);
351     wsp->GetCollectionPoint(2,3, pM);
352     vtkMath::Subtract(pM,pC,pM2);
353     vtkMath::Cross(pM1,pM2,pM);
354     n2[0] = n2[0] + pM[0];
355     n2[1] = n2[1] + pM[1];
356     n2[2] = n2[2] + pM[2];
357
358     wsp->GetCollectionPoint(2,3, pM);
359     vtkMath::Subtract(pM,pC,pM1);
360     wsp->GetCollectionPoint(2,0, pM);
361     vtkMath::Subtract(pM,pC,pM2);
362     vtkMath::Cross(pM1,pM2,pM);
363     n2[0] = n2[0] + pM[0];
364     n2[1] = n2[1] + pM[1];
365     n2[2] = n2[2] + pM[2];
366     
367     wsp->GetCollectionPoint(2,0, pM);
368     vtkMath::Subtract(pM,pC,pM1);
369     wsp->GetCollectionPoint(0,0, pM);
370     vtkMath::Subtract(pM,pC,pM2);
371     vtkMath::Cross(pM1,pM2,pM);
372     n2[0] = n2[0] + pM[0];
373     n2[1] = n2[1] + pM[1];
374     n2[2] = n2[2] + pM[2];
375     
376     n2[0] = n2[0] / 4;
377     n2[1] = n2[1] / 4;
378     n2[2] = n2[2] / 4;
379     
380 //        3. Calcular el angulo entre V1 y V2
381     double angle = vtkMath::AngleBetweenVectors(n1,n2) * 180 / vtkMath::Pi();
382 //        4. Si el angulo es major de 90 Invertir las normales de la superficie actual
383     if (angle<90)
384     {
385         vtkMath::MultiplyScalar(n2, -1);
386         wsp->InvertLstPoints_();
387     } // if angle
388     std::vector<double> normalOut(n2, n2 + 3);
389     double norm = vtkMath::Norm(n2);
390     normalOut[0] = normalOut[0]/norm;
391         normalOut[1] = normalOut[1]/norm;
392         normalOut[2] = normalOut[2]/norm;
393         
394         std::vector<double> outputData;
395         outputData.insert(outputData.end(), &centroid[0], &centroid[3]);
396         outputData.insert(outputData.end(), &normalOut[0], &normalOut[3]);
397         
398         bbSetOutputOut(outputData);
399     //bbSetOutputOut(normalOut);
400     
401     // --- Finish ---
402     wsp->SetOutputBox();
403     wsp->UndoRedo_SaveCollection();
404 }
405
406 void ShowNPoints_Tools::MovePatchCenter()
407 {       
408         std::vector<double> params = bbGetInputParams();
409         if(params.size() == 4)
410         {
411                 if(params[3] != 1 && params[3] != -1)
412                 {
413                         printf("PG ShowNPoints_Tools::MovePatchCenter()  Warning params are wrong. direction of movement should be 1 or -1\n");
414                         return;
415                 }
416                 
417                 double centerPoint[3];
418                 std::vector<double> normal, modPoint;
419                 
420                 normal.push_back(params[0]);
421                 normal.push_back(params[1]);
422                 normal.push_back(params[2]);
423
424                 int direction = -1 * params[3];
425                 
426                 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
427                 wsp->GetCollectionPoint(1,1, centerPoint);
428                 modPoint.push_back(centerPoint[0] + direction * normal[0]);
429                 modPoint.push_back(centerPoint[1] + direction * normal[1]);
430                 modPoint.push_back(centerPoint[2] + direction * normal[2]);
431
432                 wsp->SetCollectionPoint(1, 1, modPoint);
433         
434         // --- Finish ---
435         wsp->SetOutputBox();
436         wsp->UndoRedo_SaveCollection();
437         }else{
438                 printf("PG ShowNPoints_Tools::MovePatchCenter()  Warning params are wrong. Need 4: normal x y z and direction of movement (1 or -1)\n");
439         }
440 }
441
442 /**
443 *       Creates a cutting surface with 1 group of points. This surface can have its area adjusted 
444 *       (increase or decrease the distance from the points to the center)
445 *       The centroid is set as the output, to be used by the expanding tool.
446 */
447 void ShowNPoints_Tools::CreateExpandedSurface()
448 {
449         //
450         //Set Input to 0 as this function should only be executed manually but still update its children.
451         bbSetInputType(0);
452         //
453         //
454         WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
455         wsp->StopAutoAddPoints();
456     wsp->StopTrackPoint();
457         if((wsp->GetLstModelShowNPointsSize()==1) && (bbGetInputMesh()!=NULL ) && (wsp->GetModelShowNPoints()->GetLstPointsSize()>0))
458         {       
459                 //Set Input to 0 as this function should only be executed manually but still update its children.
460                 //bbSetInputType(0);
461                 //
462                 std::vector<double> lstX = wsp->GetModelShowNPoints()->GetLstPointsX();
463                 std::vector<double> lstY = wsp->GetModelShowNPoints()->GetLstPointsY();
464                 std::vector<double> lstZ = wsp->GetModelShowNPoints()->GetLstPointsZ();
465                 
466                 wsp->DeleteAllPoints_();
467                 double centroid[3];
468                 
469                 for(int i = 0; i < (int)lstX.size(); i++){
470                         centroid[0] += lstX[i];
471                         centroid[1] += lstY[i];
472                         centroid[2] += lstZ[i];
473                 }
474                 centroid[0] /= lstX.size();
475                 centroid[1] /= lstX.size();
476                 centroid[2] /= lstX.size();
477                 
478                 double p[3];
479                 double dV[3];
480                 
481                 for(int i = 0; i < (int)lstX.size(); i++){
482                         dV[0] = lstX[i] - centroid[0];
483                         dV[1] = lstY[i] - centroid[1];
484                         dV[2] = lstZ[i] - centroid[2];
485                         vtkMath::Normalize(dV);
486                         
487                         p[0] = lstX[i] + 4*dV[0];
488                         p[1] = lstY[i] + 4*dV[1];
489                         p[2] = lstZ[i] + 4*dV[2];
490                         wsp->AddPoint(p[0] ,p[1], p[2],"");
491                 }
492                 std::vector<double> outData = {centroid[0], centroid[1], centroid[2]};
493                 bbSetOutputOut(outData);
494         }
495         else{
496                 printf("PG ShowNPoints_Tools::CreateExpandedSurface  Warning surface not apply. groups, mesh or points invalid. need 1 group of points\n");
497         }
498         // --- Finish ---
499         wsp->SetOutputBox();
500         wsp->UndoRedo_SaveCollection();
501 }
502
503 /**
504 *       Creates a cutting surface with 3 groups of points. This surface can have its area adjusted
505 *       (Increase or decrease distance from points to centroid of spline or distance between splines)
506 *       The centroid and normal is set as the Output, to be used by the expanding tools.
507 */
508 void ShowNPoints_Tools::CreateWideExpandedSurface()
509 {
510         //
511         //Set Input to 0 as this function is only used by the popup menu
512         //bbSetInputType(0);
513         //
514         //
515         WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
516         wsp->StopAutoAddPoints();
517     wsp->StopTrackPoint();
518     
519         if((wsp->GetLstModelShowNPointsSize()==1) && (bbGetInputMesh()!=NULL ) && (wsp->GetModelShowNPoints()->GetLstPointsSize()>0))
520         {       
521                 std::vector<double> lstX = wsp->GetModelShowNPoints()->GetLstPointsX();
522                 std::vector<double> lstY = wsp->GetModelShowNPoints()->GetLstPointsY();
523                 std::vector<double> lstZ = wsp->GetModelShowNPoints()->GetLstPointsZ();
524                 
525                 wsp->DeleteAllPoints_();
526                 
527                 double normal[3];
528                 double centroid[3];
529                         
530                 for(int i = 0; i < (int)lstX.size(); i++){
531                         centroid[0] += lstX[i];
532                         centroid[1] += lstY[i];
533                         centroid[2] += lstZ[i];
534                 }
535                 centroid[0] /= lstX.size();
536                 centroid[1] /= lstX.size();
537                 centroid[2] /= lstX.size();
538                 
539                 double v1[3], v2[3];
540                 double currNormal[3];
541                 
542                 for(int i = 0; i < ((int)lstX.size())-1; i++){
543                         v1[0] = lstX[i] - centroid[0];
544                         v1[1] = lstY[i] - centroid[1];
545                         v1[2] = lstZ[i] - centroid[2];          
546                         v2[0] = lstX[i+1] - centroid[0];
547                         v2[1] = lstY[i+1] - centroid[1];
548                         v2[2] = lstZ[i+1] - centroid[2];
549                         vtkMath::Cross(v1, v2, currNormal);
550                         normal[0] += currNormal[0];
551                         normal[1] += currNormal[1];
552                         normal[2] += currNormal[2];
553                 }
554                 
555                 normal[0] /= (lstX.size()-1);
556                 normal[1] /= (lstX.size()-1);
557                 normal[2] /= (lstX.size()-1);
558                 
559                 vtkMath::Normalize(normal);
560                 
561                 double np[3], dV[3];
562                 int     addNormal = 1;
563                 //Add new groups on both sides from the original spline
564                 for(int group = 0; group < 2; group++){
565                         for(int i = 0; i < (int) lstX.size(); i++){
566                                 dV[0] = lstX[i] - centroid[0];
567                                 dV[1] = lstY[i] - centroid[1];
568                                 dV[2] = lstZ[i] - centroid[2];
569                                 vtkMath::Normalize(dV);
570                                 
571                                 np[0] = lstX[i] + dV[0]*4 + ((normal[0]*2)*addNormal);
572                                 np[1] = lstY[i] + dV[1]*4 + ((normal[1]*2)*addNormal);
573                                 np[2] = lstZ[i] + dV[2]*4 + ((normal[2]*2)*addNormal);
574                                 wsp->AddPoint(np[0] ,np[1], np[2],"");
575                         }
576                         addNormal = -1;
577                         if(group < 1)wsp->InsertCollectionAfter_();
578                 }
579                 
580                 std::vector<double> outData = {centroid[0], centroid[1], centroid[2], normal[0], normal[1], normal[2]};
581                 bbSetOutputOut(outData);
582                 
583                 // --- Finish ---
584         wsp->SetOutputBox();
585         wsp->UndoRedo_SaveCollection();
586         }
587         else{
588                 printf("PG ShowNPoints_Tools::CreateWideExpandedSurface  Warning surface not apply. groups, mesh or points invalid. need 1 group of points\n");
589         }
590 }
591
592 /**
593 *       Given a cutting surface, expand its area by moving the points outwards of the main centroid.
594 */
595 void ShowNPoints_Tools::ExpandSurfaceArea()
596 {
597         WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
598         wsp->StopAutoAddPoints();
599     wsp->StopTrackPoint();
600     
601         if((wsp->GetLstModelShowNPointsSize()==1 || wsp->GetLstModelShowNPointsSize() == 2)  
602                 && (wsp->GetModelShowNPoints()->GetLstPointsSize()>0)
603                 && (bbGetInputParams().size() == 4))
604         {
605                 std::vector<double> params = bbGetInputParams();
606                 double direction = params[3];
607                 double centroid[3] = {params[0], params[1], params[2]};
608                 
609                 double dV[3], currPoint[3], mdfdPoint[3];
610                 
611                 std::vector<double> modPoint;
612                 int pointsPerSpline = wsp->GetModelShowNPoints()->GetLstPointsSize();
613                 for(int i = 0; i < pointsPerSpline; i++){
614                         wsp->GetCollectionPoint(0, i, currPoint);
615                         dV[0] = currPoint[0] - centroid[0];
616                         dV[1] = currPoint[1] - centroid[1];
617                         dV[2] = currPoint[2] - centroid[2];
618                         vtkMath::Normalize(dV);
619                         
620                         vtkMath::MultiplyScalar(dV, direction);
621                         vtkMath::Add(currPoint, dV, mdfdPoint);
622                         modPoint.insert(modPoint.begin(), std::begin(mdfdPoint), std::end(mdfdPoint));
623                         wsp->SetCollectionPoint(0, i, modPoint);
624                         
625                         if(wsp->GetLstModelShowNPointsSize() == 2){
626                                 wsp->GetCollectionPoint(1, i, currPoint);
627                                 vtkMath::Add(currPoint, dV, mdfdPoint);
628                                 modPoint.insert(modPoint.begin(), std::begin(mdfdPoint), std::end(mdfdPoint));
629                                 wsp->SetCollectionPoint(1, i, modPoint);
630                         }
631                 }
632         }
633         else{
634                 printf("PG ShowNPoints_Tools::ExpandSurface  Warning surface not apply. groups, points or params invalid. need 1 group of points, need 4 params(centroid and direction)\n");
635         }
636         // --- Finish ---
637         wsp->SetOutputBox();
638         wsp->UndoRedo_SaveCollection();
639 }
640
641 void ShowNPoints_Tools::ExpandPatch()
642 {
643         WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
644         wsp->StopAutoAddPoints();
645     wsp->StopTrackPoint();
646         if((wsp->GetLstModelShowNPointsSize() == 3)  
647                 && (wsp->GetLstPointsX().size() == 13)
648                 && (bbGetInputParams().size() == 4))
649         {
650                 std::vector<double> params = bbGetInputParams();
651                 double direction = params[3];
652                 double centroid[3] = {params[0], params[1], params[2]};
653
654                 std::vector<double> modPoint(3);
655                 double currentPoint[3], dV[3], mdfdPoint[3];
656                 for(int group = 0; group < 3; group++){
657                         if(group == 1){
658                                 wsp->GetCollectionPoint(group, 0, currentPoint);
659                                 dV[0] = currentPoint[0] - centroid[0];
660                                 dV[1] = currentPoint[1] - centroid[1];
661                                 dV[2] = currentPoint[2] - centroid[2];
662                                 vtkMath::Normalize(dV);
663                                 vtkMath::MultiplyScalar(dV, direction);
664                                 vtkMath::Add(currentPoint, dV, mdfdPoint);
665                                 modPoint.insert(modPoint.begin(), std::begin(mdfdPoint), std::end(mdfdPoint));
666                                 wsp->SetCollectionPoint(group, 0, modPoint);
667                                 wsp->GetCollectionPoint(group, 2, currentPoint);
668                                 dV[0] = currentPoint[0] - centroid[0];
669                                 dV[1] = currentPoint[1] - centroid[1];
670                                 dV[2] = currentPoint[2] - centroid[2];
671                                 vtkMath::Normalize(dV);
672                                 vtkMath::MultiplyScalar(dV, direction);
673                                 vtkMath::Add(currentPoint, dV, mdfdPoint);
674                                 modPoint.insert(modPoint.begin(), std::begin(mdfdPoint), std::end(mdfdPoint));
675                                 wsp->SetCollectionPoint(group, 2, modPoint);
676                         }else{
677                                 for(int i = 0; i < 5; i++){
678                                         wsp->GetCollectionPoint(group,i, currentPoint);
679                                         dV[0] = currentPoint[0] - centroid[0];
680                                         dV[1] = currentPoint[1] - centroid[1];
681                                         dV[2] = currentPoint[2] - centroid[2];
682                                         vtkMath::Normalize(dV);
683                                         vtkMath::MultiplyScalar(dV, direction);
684                                         vtkMath::Add(currentPoint, dV, mdfdPoint);
685                                         modPoint.insert(modPoint.begin(), std::begin(mdfdPoint), std::end(mdfdPoint));
686                                         wsp->SetCollectionPoint(group, i, modPoint);
687                                 }
688                         }
689                 }
690         }else{
691                 printf("PG ShowNPoints_Tools::ExpandPatch  Warning groups, points or params invalid. need 3 groups of points, need 4 params(centroid, and direction 1 or -1)\n");
692         }
693         // --- Finish ---
694         wsp->SetOutputBox();
695         wsp->UndoRedo_SaveCollection();
696 }
697
698 /**
699 *       Given a cutting surface, expand the distance between the edge splines and the middle spline. making it "wider" or "thicker".
700 */
701 void ShowNPoints_Tools::WidenSurface()
702 {
703         WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
704         wsp->StopAutoAddPoints();
705     wsp->StopTrackPoint();
706
707         if((wsp->GetLstModelShowNPointsSize()==2)  
708                 && (wsp->GetModelShowNPoints()->GetLstPointsSize()>0)
709                 && (bbGetInputParams().size() == 4))
710         {
711                 double direction = bbGetInputParams()[3];
712                 double normal[3] = {bbGetInputParams()[0], bbGetInputParams()[1], bbGetInputParams()[2]};
713                 vtkMath::MultiplyScalar(normal, direction);
714                 
715                 int pointsPerSpline = wsp->GetModelShowNPoints()->GetLstPointsSize();
716                 double pointSp1[3], pointSp2[3];
717                 std::vector<double> modifiedPoint;
718                 for(int i = 0; i < pointsPerSpline; i++){
719                         wsp->GetCollectionPoint(0, i, pointSp1);
720                         wsp->GetCollectionPoint(1, i, pointSp2);
721                         vtkMath::Add(pointSp1, normal, pointSp1);
722                         vtkMath::Subtract(pointSp2, normal, pointSp2);
723                         modifiedPoint.insert(modifiedPoint.begin(), std::begin(pointSp1), std::end(pointSp1));
724                         wsp->SetCollectionPoint(0, i, modifiedPoint);
725                         modifiedPoint.insert(modifiedPoint.begin(), std::begin(pointSp2), std::end(pointSp2));
726                         wsp->SetCollectionPoint(1, i, modifiedPoint);
727                 }
728         
729         }else{
730                 printf("PG ShowNPoints_Tools::WidenSurface  Warning surface not apply. groups, points or params invalid. need 3 group of points, need 4 params(normal and direction)\n");
731         }
732         // --- Finish ---
733         wsp->SetOutputBox();
734         wsp->UndoRedo_SaveCollection();
735 }
736
737 void ShowNPoints_Tools::MovePointInNormal()
738 {
739         //move the currently selected control point in the direction or opposite of the normal vector of the closest point in the input mesh
740
741         WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
742         wsp->StopAutoAddPoints();
743     wsp->StopTrackPoint();
744     if((wsp->GetLstModelShowNPointsSize()>=2)  //Check condition
745                 && (wsp->GetModelShowNPoints()->GetLstPointsSize()>0)
746                 && (bbGetInputParams().size() == 1)
747                 && (bbGetInputMesh() != NULL)
748                 && (bbGetInputSpacing().size() == 3))
749         {
750                 if(bbGetInputParams()[0] != -1 && bbGetInputParams()[0] != 1){
751                         printf("PG ShowNPoints_Tools::MovePointInNormal No direction provided, must be 1 or -1");
752                         return;
753                 }
754                 double spc[3];
755         double x,y,z;
756         double p[3], normal[3];;         // point to modify and normal
757         std::vector<double> pN(3);    // new point
758
759         spc[0]                                                          = bbGetInputSpacing()[0];
760         spc[1]                                                          = bbGetInputSpacing()[1];
761         spc[2]                                                          = bbGetInputSpacing()[2];
762         
763         vtkStaticPointLocator   *pointLocator   = vtkStaticPointLocator::New();
764         pointLocator->SetDataSet( bbGetInputMesh() );
765         pointLocator->BuildLocator();
766         
767 //        int idControlPoint = wsp->GetModelShowNPoints()->GetNearestPoint();
768         int idControlPoint = wsp->GetModelShowNPoints()->GetIdCurrentPoint();
769         
770         if(idControlPoint >= 0){
771                     wsp->GetModelShowNPoints()->GetIdPoint(idControlPoint, &x, &y, &z);
772                     p[0] = x * spc[0];
773                     p[1] = y * spc[1];
774                     p[2] = z * spc[2];
775                     int idMeshPoint = pointLocator->FindClosestPoint(p);
776                     bbGetInputMesh()->GetPointData()->GetNormals()->GetTuple(idMeshPoint, normal);
777                         int direction = bbGetInputParams()[0];
778                     pN[0] = p[0] / spc[0] + direction*normal[0];
779                     pN[1] = p[1] / spc[1] + direction*normal[1];
780                     pN[2] = p[2] / spc[2] + direction*normal[2];
781                     
782                     wsp->GetModelShowNPoints()->SetPointById(idControlPoint, pN);
783                     wsp->GetViewShowNPoints()->RefreshPoint(idControlPoint);
784                     wsp->SetOutputBox();
785                 wsp->UndoRedo_SaveCollection();
786         } // if idControlPoint
787         } //wsp
788 }
789
790 void ShowNPoints_Tools::ChangeCurrentPoint()
791 {
792     if(bbGetInputParams()[0] != -1 && bbGetInputParams()[0] != 1){
793         printf("PG ShowNPoints_Tools::MovePointInNormal No direction provided, must be 1 or -1");
794         return;
795     } // if Params
796     int step=bbGetInputParams()[0];
797     WidgetShowNPoints   *wsp            = bbGetInputWidgetShowNPoints();
798     int                 idControlPoint  = wsp->GetModelShowNPoints()->GetIdCurrentPoint() + step;
799     int size=wsp->GetModelShowNPoints()->GetLstPointsSize();
800     if (idControlPoint<0)       { idControlPoint = size-1;  }
801     if (idControlPoint>=size )  { idControlPoint = 0;       }
802     wsp->GetModelShowNPoints()->SetIdCurrentPoint( idControlPoint );
803     wsp->RefreshCollectionText();
804     wsp->RefreshColourCollection();
805 }
806
807 void ShowNPoints_Tools::JoinPoints()
808 {
809         WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
810         wsp->StopAutoAddPoints();
811     wsp->StopTrackPoint();
812     if((wsp->GetLstModelShowNPointsSize()>=2)
813                 && (wsp->GetModelShowNPoints()->GetLstPointsSize()>0))
814         {
815                 int numberOfSplines = wsp->GetLstModelShowNPointsSize();
816                 double x, y, z;
817                 int sizeCurrentSpline, i;
818                 wsp->GetModelShowNPoints()->GetIdPoint(0, &x, &y, &z);
819                 std::vector<double> pointStart = {x, y, z};
820                 sizeCurrentSpline = wsp->GetModelShowNPoints()->GetLstPointsX().size();
821                 wsp->GetModelShowNPoints()->GetIdPoint(sizeCurrentSpline-1, &x, &y, &z);
822                 std::vector<double> pointEnd = {x, y, z};
823                 for(i = 0; i < numberOfSplines; i++){
824                         sizeCurrentSpline = wsp->GetModelShowNPoints(i)->GetLstPointsX().size();
825                         wsp->SetCollectionPoint(i, 0, pointStart);
826                         wsp->SetCollectionPoint(i, sizeCurrentSpline-1, pointEnd);
827                 }
828                 wsp->SetOutputBox();
829         wsp->UndoRedo_SaveCollection();
830         } // if Size
831 }
832
833 //=====
834 // 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)
835 //===== 
836 void ShowNPoints_Tools::Process()
837 {
838
839 // THE MAIN PROCESSING METHOD BODY
840 //   Here we simply set the input 'In' value to the output 'Out'
841 //   And print out the output value
842 // INPUT/OUTPUT ACCESSORS ARE OF THE FORM :
843 //    void bbSet{Input|Output}NAME(const TYPE&)
844 //    const TYPE& bbGet{Input|Output}NAME() const 
845 //    Where :
846 //    * NAME is the name of the input/output
847 //      (the one provided in the attribute 'name' of the tag 'input')
848 //    * TYPE is the C++ type of the input/output
849 //      (the one provided in the attribute 'type' of the tag 'input')
850
851 //    bbSetOutputOut( bbGetInputIn() );
852 //    std::cout << "Output value = " <<bbGetOutputOut() << std::endl;
853
854     if (bbGetInputWidgetShowNPoints()!=NULL)
855     {
856         if (bbGetInputType()==1)
857         {
858             bbGetInputWidgetShowNPoints()->OnAutoAddPoints_tool();
859         } // if Type
860
861         if (bbGetInputType()==5)
862         {
863             bbGetInputWidgetShowNPoints()->OnAddPoint_();
864         } // if Type
865         if (bbGetInputType()==10)
866         {
867             bbGetInputWidgetShowNPoints()->OnInsertPoint_();
868         } // if Type
869         if (bbGetInputType()==20)
870         {
871             bbGetInputWidgetShowNPoints()->OnTrackPoint_tool();
872         } // if Type
873         if (bbGetInputType()==30)
874         {
875             bbGetInputWidgetShowNPoints()->OnSetPoint_();
876         } // if Type
877         if (bbGetInputType()==40)
878         {
879             bbGetInputWidgetShowNPoints()->OnErasePoint_();
880         } // if Type
881         if (bbGetInputType()==50)
882         {
883             bbGetInputWidgetShowNPoints()->OnDeleteAllPoints_();
884         } // if Type
885         if (bbGetInputType()==100)
886         {
887             bbGetInputWidgetShowNPoints()->OnInsertCollectionAfter_();
888         } // if Type
889         if (bbGetInputType()==110)
890         {
891             bbGetInputWidgetShowNPoints()->OnDeleteCollection_();
892         } // if Type
893         if (bbGetInputType()==120)
894         {
895             bbGetInputWidgetShowNPoints()->OnResetCollections_();
896         } // if Type
897         if (bbGetInputType()==200)   // Create patch surface
898         {
899             InitCreatePatch_Points();
900         } // if Type
901         if (bbGetInputType()==205)  // Create volume surface from points
902         {
903             InitCreateVolumeSurface_Points();
904         } // if Type
905         if (bbGetInputType()==210)
906         {
907             bbGetInputWidgetShowNPoints()->OnInvertLstPoints_();
908         } // if Type
909         if(bbGetInputType()==220)
910         {
911                 MovePatchCenter();
912         } // if Type
913         if(bbGetInputType()==230)
914         {
915                 MovePointInNormal();
916         } // if Type
917         if(bbGetInputType()==235)
918         {
919             ChangeCurrentPoint();
920         } // if Type
921
922         if(bbGetInputType()==240)
923         {
924                 JoinPoints();
925         } // if Type
926         if(bbGetInputType()==300)
927         {
928                 CreateExpandedSurface();
929         } // if Type
930         if(bbGetInputType()==310)
931         {
932                 CreateWideExpandedSurface();
933         } // if Type
934         if(bbGetInputType()==320)
935         {
936                 ExpandSurfaceArea();
937         } // if Type
938         if(bbGetInputType()==330)
939         {
940                 WidenSurface();
941         } // if Type
942         if(bbGetInputType()==340)
943         {
944                 ExpandPatch();
945         } // if Type
946     } // if bbGetInputWidgetShowNPoints
947 }
948 //===== 
949 // 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)
950 //===== 
951 void ShowNPoints_Tools::bbUserSetDefaultValues()
952 {
953 //  SET HERE THE DEFAULT INPUT/OUTPUT VALUES OF YOUR BOX 
954 //    Here we initialize the input 'In' to 0
955    bbSetInputType(0);
956    bbSetInputMesh(NULL);
957    bbSetInputWidgetShowNPoints(NULL);
958     
959     std::vector<double> spc;
960     spc.push_back(1);
961     spc.push_back(1);
962     spc.push_back(1);
963     bbSetInputSpacing(spc);
964 }
965 //===== 
966 // 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)
967 //===== 
968 void ShowNPoints_Tools::bbUserInitializeProcessing()
969 {
970 //  THE INITIALIZATION METHOD BODY :
971 //    Here does nothing 
972 //    but this is where you should allocate the internal/output pointers 
973 //    if any
974 }
975 //===== 
976 // 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)
977 //===== 
978 void ShowNPoints_Tools::bbUserFinalizeProcessing()
979 {
980 //  THE FINALIZATION METHOD BODY :
981 //    Here does nothing 
982 //    but this is where you should desallocate the internal/output pointers 
983 //    if any
984 }
985
986 } // EO namespace bbcreaMaracasVisu
987
988