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