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 "bbcreaMaracasVisuShowNPoints_Tools.h"
5 #include "bbcreaMaracasVisuPackage.h"
7 #include <vtkPointData.h>
8 #include <vtkDataArray.h>
12 namespace bbcreaMaracasVisu
15 BBTK_ADD_BLACK_BOX_TO_PACKAGE(creaMaracasVisu,ShowNPoints_Tools)
16 BBTK_BLACK_BOX_IMPLEMENTATION(ShowNPoints_Tools,bbtk::AtomicBlackBox);
20 void ShowNPoints_Tools::NearestPointToMesh( vtkPoints *points,vtkStaticPointLocator *pointLocator,double *spc,double *p,double *pM)
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];
31 void ShowNPoints_Tools::CreatePatch_3points()
33 //printf("PG ShowNPoints_Tools::CreatePatch_3points Entered patch 3 points !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
34 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
36 std::vector<double> lstX = wsp->GetModelShowNPoints()->GetLstPointsX();
37 std::vector<double> lstY = wsp->GetModelShowNPoints()->GetLstPointsY();
38 std::vector<double> lstZ = wsp->GetModelShowNPoints()->GetLstPointsZ();
55 vtkMath::Subtract(pC,pA,v);
56 vtkMath::Subtract(pB,pA,u);
58 /**point in AC closest to B.
59 *formula t=(V)dot(U)/(V)dot(V)
61 double t = vtkMath::Dot(v,u)/vtkMath::Dot(v,v);
63 *formula A+t(C-A) -> A+tV
65 vtkMath::MultiplyScalar(v, t);
67 vtkMath::Add(pA, v, nP);
69 //calculate direction vector from found point to B
71 vtkMath::Subtract(pB, nP, dirVector);
76 //Add and subtract direction vector to A and C to find the 4 points to create the patch,
78 std::vector<double> resListX;
79 std::vector<double> resListY;
80 std::vector<double> resListZ;
82 vtkMath::Add(pA, dirVector, pointAdd);
83 vtkMath::Subtract(pA, dirVector, pointSub);
85 resListX.push_back(pointSub[0]);
86 resListY.push_back(pointSub[1]);
87 resListZ.push_back(pointSub[2]);
89 resListX.push_back(pointAdd[0]);
90 resListY.push_back(pointAdd[1]);
91 resListZ.push_back(pointAdd[2]);
94 vtkMath::Add(pC, dirVector, pointAdd);
95 vtkMath::Subtract(pC, dirVector, pointSub);
97 resListX.push_back(pointAdd[0]);
98 resListY.push_back(pointAdd[1]);
99 resListZ.push_back(pointAdd[2]);
101 resListX.push_back(pointSub[0]);
102 resListY.push_back(pointSub[1]);
103 resListZ.push_back(pointSub[2]);
105 //Create patch given the previously calculated points (4 points)
106 CreatePatch_Points(resListX, resListY, resListZ);
109 void ShowNPoints_Tools::CreatePatch_4points()
111 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
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);
119 void ShowNPoints_Tools::InitCreatePatch_Points()
121 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
122 wsp->StopAutoAddPoints();
123 wsp->StopTrackPoint();
124 if((wsp->GetLstModelShowNPointsSize()==1) && (bbGetInputMesh()!=NULL ))
126 if(wsp->GetModelShowNPoints()->GetLstPointsSize()==4){
127 CreatePatch_4points();
129 else if(wsp->GetModelShowNPoints()->GetLstPointsSize()==3){
130 CreatePatch_3points();
133 printf("PG ShowNPoints_Tools::CreatePatch_Npoints Warning patch not apply. Number of points is invalid. Group should have 3 or 4 points\n");
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");
141 wsp->RefreshCollectionText();
142 wsp->RefreshColourCollection();
144 wsp->UndoRedo_SaveCollection();
148 void ShowNPoints_Tools::InitCreateVolumeSurface_Points()
150 InitCreatePatch_Points(); // 1 group -> 3 groups
152 // 3 groups to 4 groups
153 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
154 wsp->StopAutoAddPoints();
155 wsp->StopTrackPoint();
156 if( wsp->GetLstModelShowNPointsSize()==3 )
159 double pC1[3]; // fist point
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
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);
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;
182 wsp->InsertPoint(pC1[0] ,pC1[1], pC1[2],"");
184 NearestPointToMesh(points, pointLocator, spc, pC2A,pN);
185 wsp->InsertPoint(pN[0] ,pN[1], pN[2],"");
187 NearestPointToMesh(points, pointLocator, spc, pC2B,pN);
188 wsp->InsertPoint(pN[0] ,pN[1], pN[2],"");
190 wsp->InsertPoint(pC3[0] ,pC3[1], pC3[2],"");
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] );
202 wsp->SetActualCollection(0);
203 wsp->SetReferencePoint(pointStart);
204 wsp->OnInsertPoint_();
205 wsp->SetReferencePoint(pointEnd);
206 wsp->OnInsertPoint_();
208 wsp->SetActualCollection(2);
209 wsp->SetReferencePoint(pointStart);
210 wsp->OnInsertPoint_();
211 wsp->SetReferencePoint(pointEnd);
212 wsp->OnInsertPoint_();
215 wsp->RefreshCollectionText();
216 wsp->RefreshColourCollection();
218 wsp->UndoRedo_SaveCollection();
220 pointLocator->Delete();
226 void ShowNPoints_Tools::CreatePatch_Points(std::vector<double> lstX, std::vector<double> lstY, std::vector<double> lstZ)
228 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
229 std::vector<long int> lstIdNormalSurface;
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();
242 wsp->DeleteAllPoints_();
243 //wsp->ErasePoint( 0 );
244 //wsp->ErasePoint( 0 );
245 //wsp->ErasePoint( 0 );
246 //wsp->ErasePoint( 0 );
248 dx = lstX[1]-lstX[0];
249 dy = lstY[1]-lstY[0];
250 dz = lstZ[1]-lstZ[0];
254 for(int sect = 0; sect < 5; sect++)
256 p[0] = lstX[0] + dx*(sect*part);
257 p[1] = lstY[0] + dy*(sect*part);
258 p[2] = lstZ[0] + dz*(sect*part);
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]);
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]);
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) );
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));
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++)
298 p[0] = lstX[3] + dx*(sect*part);
299 p[1] = lstY[3] + dy*(sect*part);
300 p[2] = lstZ[3] + dz*(sect*part);
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]);
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]);
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) );
315 pointLocator->Delete();
317 // 1. Recorrer las normales de lstIdNormals y calcular el promedio -> V1
320 vtkPointData *pointdata = bbGetInputMesh()->GetPointData();
321 vtkDataArray *dataarray = pointdata->GetNormals();
322 int i,size = lstIdNormalSurface.size();
326 for (i=0; i<size; i++)
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];
337 // 2. Calcular el promedio de 4 normales de la nueva superficie -> V2
345 // Collection 0 with 4 points
346 // Collection 1 with 3 points
347 // Collection 2 with 4 points
348 wsp->GetCollectionPoint(1,1, pC);
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);
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];
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];
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];
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
395 vtkMath::MultiplyScalar(n2, -1);
396 wsp->InvertLstPoints_();
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(), ¢roid[0], ¢roid[3]);
407 outputData.insert(outputData.end(), &normalOut[0], &normalOut[3]);
409 bbSetOutputOut(outputData);
410 //bbSetOutputOut(normalOut);
414 wsp->UndoRedo_SaveCollection();
417 void ShowNPoints_Tools::MovePatchCenter()
421 std::vector<double> params = bbGetInputParams();
422 if(params.size() == 4)
424 if(params[3] != 1 && params[3] != -1)
426 printf("PG ShowNPoints_Tools::MovePatchCenter() Warning params are wrong. direction of movement should be 1 or -1\n");
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);
446 wsp->UndoRedo_SaveCollection();
448 printf("PG ShowNPoints_Tools::MovePatchCenter() Warning params are wrong. Need 4: normal x y z and direction of movement (1 or -1)\n");
452 std::vector<double> params = bbGetInputParams();
453 if(params.size() == 1)
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 );
462 printf("Error! ShowNPoints_Tools::MovePatchCenter() Warning params are wrong. Need 1 element (step ex -1 or 1)\n");
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.
471 void ShowNPoints_Tools::CreateExpandedSurface()
474 //Set Input to 0 as this function should only be executed manually but still update its children.
478 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
479 wsp->StopAutoAddPoints();
480 wsp->StopTrackPoint();
481 if((wsp->GetLstModelShowNPointsSize()==1) && (bbGetInputMesh()!=NULL ) && (wsp->GetModelShowNPoints()->GetLstPointsSize()>0))
483 //Set Input to 0 as this function should only be executed manually but still update its children.
486 std::vector<double> lstX = wsp->GetModelShowNPoints()->GetLstPointsX();
487 std::vector<double> lstY = wsp->GetModelShowNPoints()->GetLstPointsY();
488 std::vector<double> lstZ = wsp->GetModelShowNPoints()->GetLstPointsZ();
490 wsp->DeleteAllPoints_();
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];
498 centroid[0] /= lstX.size();
499 centroid[1] /= lstX.size();
500 centroid[2] /= lstX.size();
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);
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],"");
516 std::vector<double> outData = {centroid[0], centroid[1], centroid[2]};
517 bbSetOutputOut(outData);
520 printf("PG ShowNPoints_Tools::CreateExpandedSurface Warning surface not apply. groups, mesh or points invalid. need 1 group of points\n");
524 wsp->UndoRedo_SaveCollection();
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.
532 void ShowNPoints_Tools::CreateWideExpandedSurface()
535 //Set Input to 0 as this function is only used by the popup menu
539 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
540 wsp->StopAutoAddPoints();
541 wsp->StopTrackPoint();
543 if((wsp->GetLstModelShowNPointsSize()==1) && (bbGetInputMesh()!=NULL ) && (wsp->GetModelShowNPoints()->GetLstPointsSize()>0))
545 std::vector<double> lstX = wsp->GetModelShowNPoints()->GetLstPointsX();
546 std::vector<double> lstY = wsp->GetModelShowNPoints()->GetLstPointsY();
547 std::vector<double> lstZ = wsp->GetModelShowNPoints()->GetLstPointsZ();
549 wsp->DeleteAllPoints_();
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];
559 centroid[0] /= lstX.size();
560 centroid[1] /= lstX.size();
561 centroid[2] /= lstX.size();
564 double currNormal[3];
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];
579 normal[0] /= (lstX.size()-1);
580 normal[1] /= (lstX.size()-1);
581 normal[2] /= (lstX.size()-1);
583 vtkMath::Normalize(normal);
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);
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],"");
601 if(group < 1)wsp->InsertCollectionAfter_();
604 std::vector<double> outData = {centroid[0], centroid[1], centroid[2], normal[0], normal[1], normal[2]};
605 bbSetOutputOut(outData);
609 wsp->UndoRedo_SaveCollection();
612 printf("PG ShowNPoints_Tools::CreateWideExpandedSurface Warning surface not apply. groups, mesh or points invalid. need 1 group of points\n");
617 * Given a cutting surface, expand its area by moving the points outwards of the main centroid.
619 void ShowNPoints_Tools::ExpandSurfaceArea()
621 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
622 wsp->StopAutoAddPoints();
623 wsp->StopTrackPoint();
625 if((wsp->GetLstModelShowNPointsSize()==1 || wsp->GetLstModelShowNPointsSize() == 2)
626 && (wsp->GetModelShowNPoints()->GetLstPointsSize()>0)
627 && (bbGetInputParams().size() == 4))
629 std::vector<double> params = bbGetInputParams();
630 double direction = params[3];
631 double centroid[3] = {params[0], params[1], params[2]};
633 double dV[3], currPoint[3], mdfdPoint[3];
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);
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);
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);
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");
662 wsp->UndoRedo_SaveCollection();
665 void ShowNPoints_Tools::ExpandPatch()
667 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
668 wsp->StopAutoAddPoints();
669 wsp->StopTrackPoint();
670 if((wsp->GetLstModelShowNPointsSize() == 3)
671 && (wsp->GetLstPointsX().size() == 13)
672 && (bbGetInputParams().size() == 4))
674 std::vector<double> params = bbGetInputParams();
675 double direction = params[3];
676 double centroid[3] = {params[0], params[1], params[2]};
678 std::vector<double> modPoint(3);
679 double currentPoint[3], dV[3], mdfdPoint[3];
680 for(int group = 0; group < 3; group++){
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);
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);
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");
719 wsp->UndoRedo_SaveCollection();
723 * Given a cutting surface, expand the distance between the edge splines and the middle spline. making it "wider" or "thicker".
725 void ShowNPoints_Tools::WidenSurface()
727 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
728 wsp->StopAutoAddPoints();
729 wsp->StopTrackPoint();
731 if((wsp->GetLstModelShowNPointsSize()==2)
732 && (wsp->GetModelShowNPoints()->GetLstPointsSize()>0)
733 && (bbGetInputParams().size() == 4))
735 double direction = bbGetInputParams()[3];
736 double normal[3] = {bbGetInputParams()[0], bbGetInputParams()[1], bbGetInputParams()[2]};
737 vtkMath::MultiplyScalar(normal, direction);
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);
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");
758 wsp->UndoRedo_SaveCollection();
761 void ShowNPoints_Tools::MovePointInNormal()
763 //move the currently selected control point in the direction or opposite of the normal vector of the closest point in the input mesh
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))
774 if(bbGetInputParams()[0] != -1 && bbGetInputParams()[0] != 1){
775 printf("PG ShowNPoints_Tools::MovePointInNormal No direction provided, must be 1 or -1");
780 double p[3], normal[3];; // point to modify and normal
781 std::vector<double> pN(3); // new point
783 spc[0] = bbGetInputSpacing()[0];
784 spc[1] = bbGetInputSpacing()[1];
785 spc[2] = bbGetInputSpacing()[2];
787 vtkStaticPointLocator *pointLocator = vtkStaticPointLocator::New();
788 pointLocator->SetDataSet( bbGetInputMesh() );
789 pointLocator->BuildLocator();
791 // int idControlPoint = wsp->GetModelShowNPoints()->GetNearestPoint();
792 int idControlPoint = wsp->GetModelShowNPoints()->GetIdCurrentPoint();
794 if(idControlPoint >= 0){
795 wsp->GetModelShowNPoints()->GetIdPoint(idControlPoint, &x, &y, &z);
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];
806 wsp->GetModelShowNPoints()->SetPointById(idControlPoint, pN);
807 // wsp->GetViewShowNPoints()->RefreshPoint(idControlPoint);
808 wsp->RefreshCollectionText();
809 wsp->RefreshColourCollection();
811 wsp->UndoRedo_SaveCollection();
812 } // if idControlPoint
813 } // if wsp->GetLstModelShowNPointsSiz->size()>=2
816 void ShowNPoints_Tools::ChangeCurrentPoint()
818 if(bbGetInputParams()[0] != -1 && bbGetInputParams()[0] != 1){
819 printf("PG ShowNPoints_Tools::MovePointInNormal No direction provided, must be 1 or -1");
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();
833 void ShowNPoints_Tools::JoinPoints()
835 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
836 wsp->StopAutoAddPoints();
837 wsp->StopTrackPoint();
838 if((wsp->GetLstModelShowNPointsSize()>=2)
839 && (wsp->GetModelShowNPoints()->GetLstPointsSize()>0))
841 int numberOfSplines = wsp->GetLstModelShowNPointsSize();
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);
855 wsp->UndoRedo_SaveCollection();
859 void ShowNPoints_Tools::SetMesh()
861 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
862 wsp->SetAuxMesh(bbGetInputMesh(), bbGetInputSpacing(), bbGetInputParams() );
865 void ShowNPoints_Tools::SeparateSplines()
867 WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
868 if((wsp->GetLstModelShowNPointsSize() > 0) && (bbGetInputParams().size() == 6))
870 std::vector<double> refPoint = {bbGetInputParams()[0], bbGetInputParams()[1], bbGetInputParams()[2]};
871 std::vector<double> pointsX, pointsY, pointsZ, refPlaneNorm, planeNormal;
872 std::vector<std::vector<std::vector<double>>> newGroups;
873 std::vector<std::vector<double>> planesNorm;
875 std::vector<double> rotAxis = {bbGetInputParams()[3], bbGetInputParams()[4], bbGetInputParams()[5]}; ;
877 std::vector<double> intersectionTop, intersectionBottom;
879 int numGroups = wsp->GetLstModelShowNPointsSize();
880 for(int i = 0; i < numGroups; i++){
881 pointsX = wsp->GetModelShowNPoints(i)->GetLstPointsX();
882 pointsY = wsp->GetModelShowNPoints(i)->GetLstPointsY();
883 pointsZ = wsp->GetModelShowNPoints(i)->GetLstPointsZ();
885 planeNormal = GetPlaneNormalFromPointsRefPoint(pointsX, pointsY, pointsZ, refPoint);
888 refPlaneNorm = planeNormal;
891 //Get points over, under and on plane, all groups ordered in the direction of the axis.
892 std::vector<std::vector<std::vector<double>>> pointsAroundPlane;
893 pointsAroundPlane = GetOrderedPointsAroundPlane(refPoint, planeNormal, rotAxis, pointsX, pointsY, pointsZ);
894 std::vector<std::vector<double>> pointsOver = pointsAroundPlane[0];
895 std::vector<std::vector<double>> pointsUnder = pointsAroundPlane[1];
896 std::vector<std::vector<double>> pointsOn = pointsAroundPlane[2];
897 //Calculate points where splines should intersect
898 double middlePoint[3];
899 if(intersectionTop.empty() && intersectionBottom.empty()){
900 if(!pointsOver.empty() && !pointsUnder.empty()){
901 vtkMath::Add(pointsOver.back().data(), pointsUnder.back().data(), middlePoint);
902 vtkMath::MultiplyScalar(middlePoint, 0.5);
903 intersectionTop = GetProjectionPointOnAxis(middlePoint, refPoint.data(), rotAxis.data());
905 vtkMath::Add(pointsOver.front().data(), pointsUnder.front().data(), middlePoint);
906 vtkMath::MultiplyScalar(middlePoint, 0.5);
907 intersectionBottom = GetProjectionPointOnAxis(middlePoint, refPoint.data(), rotAxis.data());
909 else if(!pointsOn.empty()){
910 intersectionTop = pointsOn.back();
911 intersectionBottom = pointsOn.front();
914 intersectionTop = pointsOver.empty()?pointsUnder.back():pointsOver.back();
915 intersectionBottom = pointsOver.empty()?pointsUnder.front():pointsOver.front();
919 //Save groups and their normals
920 if(!pointsOver.empty()){
921 pointsOver.push_back(intersectionTop);
922 pointsOver.insert(pointsOver.begin(), intersectionBottom);
923 newGroups.push_back(pointsOver);
924 planesNorm.push_back(planeNormal);
926 if(!pointsUnder.empty()){
927 pointsUnder.push_back(intersectionTop);
928 pointsUnder.insert(pointsUnder.begin(), intersectionBottom);
929 newGroups.push_back(pointsUnder);
930 double tempPlaneNorm[3] = {planeNormal[0], planeNormal[1], planeNormal[2]};
931 vtkMath::MultiplyScalar(tempPlaneNorm, -1);
932 planeNormal[0] = tempPlaneNorm[0]; planeNormal[1] = tempPlaneNorm[1]; planeNormal[2] = tempPlaneNorm[2];
933 planesNorm.push_back(planeNormal);
937 //Sort Groups by their plane angles, from the first plane around the rotation axis
938 auto comp = [&](int id1,int id2)-> bool {
939 double angle1 = vtkMath::SignedAngleBetweenVectors(planesNorm[id1].data(), refPlaneNorm.data(), rotAxis.data());
940 if(angle1 < 0) angle1 += 2*vtkMath::Pi();
941 double angle2 = vtkMath::SignedAngleBetweenVectors(planesNorm[id2].data(), refPlaneNorm.data(), rotAxis.data());
942 if(angle2 < 0) angle2 += 2*vtkMath::Pi();
943 return angle1 < angle2;
946 std::vector<int> indexVect((int)newGroups.size());
947 std::iota(std::begin(indexVect), std::end(indexVect), 0);
948 std::sort(indexVect.begin(), indexVect.end(), comp);
951 wsp->ResetCollections_();
952 for(int i = 0; i < newGroups.size(); i++){
953 std::vector<std::vector<double>> group = newGroups[indexVect[i]];
954 for(int j = 0; j < group.size(); j++){
955 std::vector<double> point = group[j];
956 wsp->AddPoint(point[0] ,point[1], point[2],"");
958 if(i < newGroups.size()-1){
959 wsp->InsertCollectionAfter_();
962 wsp->InvertLstPoints_();
964 wsp->UndoRedo_SaveCollection();
968 std::vector<std::vector<std::vector<double>>> ShowNPoints_Tools::GetOrderedPointsAroundPlane(std::vector<double> planeOrigin, std::vector<double> planeNormal, std::vector<double> rotAxis, std::vector<double> pX, std::vector<double> pY, std::vector<double> pZ){
970 std::vector<std::vector<double>> pointsOver, pointsUnder, pointsOn;
971 std::vector<double> point(3);
972 double rotatedNormal[3], vector1[3];
973 vtkMath::Cross(planeNormal.data(), rotAxis.data(), rotatedNormal);
974 vtkMath::Normalize(rotatedNormal);
976 bool changedSide = false;
977 int startingSide = -1; //-1 not started, 0 over, 1 under
978 int placedElements = 0;
979 for(int j = 0; j < pX.size(); j++){
983 vtkMath::Subtract(point.data(), planeOrigin.data(), vector1);
984 if(vtkMath::Dot(vector1, rotatedNormal) > 0){
985 if(!pointsUnder.empty()){
992 if(changedSide && startingSide == 0){
993 pointsOver.insert(pointsOver.begin()+placedElements, point);
997 pointsOver.push_back(point);
1000 else if (vtkMath::Dot(vector1, rotatedNormal) < 0){
1001 if(!pointsOver.empty())
1005 else startingSide = 1;
1007 if(changedSide && startingSide == 1){
1008 pointsUnder.insert(pointsUnder.begin()+placedElements, point);
1012 pointsUnder.push_back(point);
1016 pointsOn.push_back(point);
1021 /// Check direction of points and reverse if needed.
1022 /// Always follows axis vector direction
1023 /// remove points if size is less than or equal to 2
1025 if(pointsUnder.size() > 2){
1026 vtkMath::Subtract(pointsUnder.front(), pointsUnder.back(), vector1);
1027 double dot = vtkMath::Dot(vector1, rotAxis.data());
1029 std::reverse(pointsUnder.begin(), pointsUnder.end());
1030 if(startingSide == 1 && !pointsOn.empty()){
1031 std::reverse(pointsOn.begin(), pointsOn.end());
1036 pointsUnder.clear();
1039 if(pointsOver.size() > 2){
1040 vtkMath::Subtract(pointsOver.front(), pointsOver.back(), vector1);
1041 double dot = vtkMath::Dot(vector1, rotAxis.data());
1043 std::reverse(pointsOver.begin(), pointsOver.end());
1044 if(startingSide == 0 && !pointsOn.empty()){
1045 std::reverse(pointsOn.begin(), pointsOn.end());
1053 std::vector<std::vector<std::vector<double>>> results = {pointsOver, pointsUnder, pointsOn};
1057 std::vector<double> ShowNPoints_Tools::GetPlaneNormalFromPointsRefPoint(std::vector<double> pointsX, std::vector<double> pointsY, std::vector<double> pointsZ, std::vector<double> refPoint)
1059 double vector1[3], vector2[3], planeNormal[3];
1060 int idPoint2, idPoint3;
1061 idPoint2 = ((int)pointsX.size()/3)-1;
1062 idPoint3 = ((int)pointsX.size()/2)+1;
1064 vector1[0] = pointsX[idPoint2]-refPoint[0];
1065 vector1[1] = pointsY[idPoint2]-refPoint[1];
1066 vector1[2] = pointsZ[idPoint2]-refPoint[2];
1068 vector2[0] = pointsX[idPoint3]-refPoint[0];
1069 vector2[1] = pointsY[idPoint3]-refPoint[1];
1070 vector2[2] = pointsZ[idPoint3]-refPoint[2];
1072 vtkMath::Cross(vector1, vector2, planeNormal);
1073 vtkMath::Normalize(planeNormal);
1075 std::vector<double> result(std::begin(planeNormal), std::end(planeNormal));
1079 std::vector<double> ShowNPoints_Tools::GetProjectionPointOnAxis(double pointToProject[3], double originAxis[3], double axisDir[3])
1081 double projectionVect[3], vectorToPoint[3], pointProjected[3];
1082 vtkMath::Subtract(pointToProject, originAxis, vectorToPoint);
1084 vtkMath::ProjectVector(vectorToPoint, axisDir, projectionVect);
1085 vtkMath::Add(originAxis, projectionVect, pointProjected);
1087 std::vector<double> result(std::begin(pointProjected), std::end(pointProjected));
1093 // 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)
1095 void ShowNPoints_Tools::Process()
1098 // THE MAIN PROCESSING METHOD BODY
1099 // Here we simply set the input 'In' value to the output 'Out'
1100 // And print out the output value
1101 // INPUT/OUTPUT ACCESSORS ARE OF THE FORM :
1102 // void bbSet{Input|Output}NAME(const TYPE&)
1103 // const TYPE& bbGet{Input|Output}NAME() const
1105 // * NAME is the name of the input/output
1106 // (the one provided in the attribute 'name' of the tag 'input')
1107 // * TYPE is the C++ type of the input/output
1108 // (the one provided in the attribute 'type' of the tag 'input')
1110 // bbSetOutputOut( bbGetInputIn() );
1111 // std::cout << "Output value = " <<bbGetOutputOut() << std::endl;
1113 if (bbGetInputWidgetShowNPoints()!=NULL)
1115 if (bbGetInputType()==1)
1117 bbGetInputWidgetShowNPoints()->OnAutoAddPoints_tool();
1120 if (bbGetInputType()==5)
1122 bbGetInputWidgetShowNPoints()->OnAddPoint_();
1124 if (bbGetInputType()==10)
1126 bbGetInputWidgetShowNPoints()->OnInsertPoint_();
1128 if (bbGetInputType()==20)
1130 bbGetInputWidgetShowNPoints()->OnTrackPoint_tool();
1132 if (bbGetInputType()==30)
1134 bbGetInputWidgetShowNPoints()->OnSetPoint_();
1136 if (bbGetInputType()==40)
1138 bbGetInputWidgetShowNPoints()->OnErasePoint_();
1140 if (bbGetInputType()==50)
1142 bbGetInputWidgetShowNPoints()->OnDeleteAllPoints_();
1144 if (bbGetInputType()==100)
1146 bbGetInputWidgetShowNPoints()->OnInsertCollectionAfter_();
1148 if (bbGetInputType()==110)
1150 bbGetInputWidgetShowNPoints()->OnDeleteCollection_();
1152 if (bbGetInputType()==120)
1154 bbGetInputWidgetShowNPoints()->OnResetCollections_();
1156 if (bbGetInputType()==200) // Create patch surface
1158 InitCreatePatch_Points();
1160 if (bbGetInputType()==205) // Create volume surface from points
1162 InitCreateVolumeSurface_Points();
1164 if (bbGetInputType()==210)
1166 bbGetInputWidgetShowNPoints()->OnInvertLstPoints_();
1168 if(bbGetInputType()==220)
1172 if(bbGetInputType()==230)
1174 MovePointInNormal();
1176 if(bbGetInputType()==235)
1178 ChangeCurrentPoint();
1180 if(bbGetInputType()==240)
1184 if(bbGetInputType()==250)
1188 if(bbGetInputType()==300)
1190 CreateExpandedSurface();
1192 if(bbGetInputType()==310)
1194 CreateWideExpandedSurface();
1196 if(bbGetInputType()==320)
1198 ExpandSurfaceArea();
1200 if(bbGetInputType()==330)
1204 if(bbGetInputType()==340)
1208 if(bbGetInputType()==400)
1212 } // if bbGetInputWidgetShowNPoints
1215 // 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)
1217 void ShowNPoints_Tools::bbUserSetDefaultValues()
1219 // SET HERE THE DEFAULT INPUT/OUTPUT VALUES OF YOUR BOX
1220 // Here we initialize the input 'In' to 0
1222 bbSetInputMesh(NULL);
1223 bbSetInputWidgetShowNPoints(NULL);
1225 std::vector<double> spc;
1229 bbSetInputSpacing(spc);
1232 // 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)
1234 void ShowNPoints_Tools::bbUserInitializeProcessing()
1236 // THE INITIALIZATION METHOD BODY :
1237 // Here does nothing
1238 // but this is where you should allocate the internal/output pointers
1242 // 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)
1244 void ShowNPoints_Tools::bbUserFinalizeProcessing()
1246 // THE FINALIZATION METHOD BODY :
1247 // Here does nothing
1248 // but this is where you should desallocate the internal/output pointers
1252 } // EO namespace bbcreaMaracasVisu