Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/gui.git] / src / VTKViewer / VTKViewer_ConvexTool.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
2 // 
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either 
6 // version 2.1 of the License.
7 // 
8 // This library is distributed in the hope that it will be useful 
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public  
14 // License along with this library; if not, write to the Free Software 
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 //  This library is distributed in the hope that it will be useful, 
20 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
21 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
22 //  Lesser General Public License for more details. 
23 // 
24 //  You should have received a copy of the GNU Lesser General Public 
25 //  License along with this library; if not, write to the Free Software 
26 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
27 // 
28 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
29
30 #include "VTKViewer_ConvexTool.h"
31
32 #include <set>
33 #include <map>
34
35 #include <vtkUnstructuredGrid.h>
36 #include <vtkGeometryFilter.h>
37 #include <vtkDelaunay3D.h>
38 #include <vtkGenericCell.h>
39 #include <vtkPolyData.h>
40 #include <vtkCellData.h>
41 #include <vtkPoints.h>
42 #include <vtkIdList.h>
43 #include <vtkCell.h>
44 #include <vtkPlane.h>
45 #include <vtkMath.h>
46
47 namespace
48 {
49   typedef std::vector<vtkIdType> TConnectivities;
50
51   struct TPolygon
52   {
53     TConnectivities myConnectivities;
54     vtkFloatingPointType myOrigin[3];
55     vtkFloatingPointType myNormal[3];
56     TPolygon(const TConnectivities& theConnectivities,
57              vtkFloatingPointType theOrigin[3],
58              vtkFloatingPointType theNormal[3]):
59       myConnectivities(theConnectivities)
60     {
61       myOrigin[0] = theOrigin[0];
62       myOrigin[1] = theOrigin[1];
63       myOrigin[2] = theOrigin[2];
64
65       myNormal[0] = theNormal[0];
66       myNormal[1] = theNormal[1];
67       myNormal[2] = theNormal[2];
68     }
69   };
70
71   typedef std::vector<TPolygon> TPolygons;
72 }
73
74 /*!
75   Constructor
76 */
77 VTKViewer_Triangulator
78 ::VTKViewer_Triangulator():
79   myInput(NULL),
80   myCellId(-1),
81   myShowInside(-1),
82   myAllVisible(-1),
83   myCellsVisibility(NULL),
84   myCellIds(vtkIdList::New())
85 {}
86
87
88 /*!
89   Destructor
90 */
91 VTKViewer_Triangulator
92 ::~VTKViewer_Triangulator()
93 {
94   myCellIds->Delete();
95 }
96
97
98
99 bool 
100 VTKViewer_Triangulator
101 ::Execute(vtkUnstructuredGrid *theInput,
102           vtkCellData* thInputCD,
103           vtkIdType theCellId,
104           int theShowInside,
105           int theAllVisible,
106           const char* theCellsVisibility,
107           vtkPolyData *theOutput,
108           vtkCellData* theOutputCD,
109           int theStoreMapping,
110           std::vector<vtkIdType>& theVTK2ObjIds,
111           bool theIsCheckConvex)
112 {
113   myInput = theInput;
114   myCellId = theCellId;
115   myShowInside = theShowInside;
116   myAllVisible = theAllVisible;
117   myCellsVisibility = theCellsVisibility;
118
119   vtkPoints *aPoints = InitPoints();
120   vtkIdType aNumPts = GetNbOfPoints();
121   //cout<<"Triangulator - aNumPts = "<<aNumPts<<"\n";
122
123   if(aNumPts == 0)
124     return true;
125
126   // To calculate the bary center of the cell
127   vtkFloatingPointType aCellCenter[3] = {0.0, 0.0, 0.0};
128   {
129     vtkFloatingPointType aPntCoord[3];
130     for (int aPntId = 0; aPntId < aNumPts; aPntId++) {
131       aPoints->GetPoint(GetPointId(aPntId),aPntCoord);
132       //cout<<"\taPntId = "<<aPntId<<" {"<<aPntCoord[0]<<", "<<aPntCoord[1]<<", "<<aPntCoord[2]<<"}\n";
133       aCellCenter[0] += aPntCoord[0];
134       aCellCenter[1] += aPntCoord[1];
135       aCellCenter[2] += aPntCoord[2];
136     }
137     aCellCenter[0] /= aNumPts;
138     aCellCenter[1] /= aNumPts;
139     aCellCenter[2] /= aNumPts;
140   }
141
142   vtkFloatingPointType aCellLength = GetCellLength();
143   int aNumFaces = GetNumFaces();
144
145   static vtkFloatingPointType EPS = 1.0E-2;
146   vtkFloatingPointType aDistEps = aCellLength * EPS;
147   //cout<<"\taCellLength = "<<aCellLength<<"; aDistEps = "<<aDistEps<<"\n";
148
149   // To initialize set of points that belong to the cell
150   typedef std::set<vtkIdType> TPointIds;
151   TPointIds anInitialPointIds;
152   for(vtkIdType aPntId = 0; aPntId < aNumPts; aPntId++)
153     anInitialPointIds.insert(GetPointId(aPntId));
154   
155   // To initialize set of points by face that belong to the cell and backward
156   typedef std::set<vtkIdType> TFace2Visibility;
157   TFace2Visibility aFace2Visibility;
158   
159   typedef std::set<TPointIds> TFace2PointIds;
160   TFace2PointIds aFace2PointIds;
161
162   for (int aFaceId = 0; aFaceId < aNumFaces; aFaceId++) {
163     vtkCell* aFace = GetFace(aFaceId);
164     
165     GetCellNeighbors(theCellId, aFace, myCellIds);
166     if((!myAllVisible && !myCellsVisibility[myCellIds->GetId(0)]) || 
167        myCellIds->GetNumberOfIds() <= 0 || myShowInside)
168     {
169       TPointIds aPointIds;
170       vtkIdList *anIdList = aFace->PointIds;  
171       aPointIds.insert(anIdList->GetId(0));
172       aPointIds.insert(anIdList->GetId(1));
173       aPointIds.insert(anIdList->GetId(2));
174       
175       aFace2PointIds.insert(aPointIds);
176       aFace2Visibility.insert(aFaceId);
177     }
178   }
179
180
181   ::TPolygons aPolygons;
182
183   for (int aFaceId = 0; aFaceId < aNumFaces; aFaceId++) {
184     if(aFace2Visibility.find(aFaceId) == aFace2Visibility.end())
185       continue;
186
187     vtkCell* aFace = GetFace(aFaceId);
188
189     vtkIdList *anIdList = aFace->PointIds;
190     vtkIdType aNewPts[3] = {anIdList->GetId(0), anIdList->GetId(1), anIdList->GetId(2)};
191             
192     // To initialize set of points for the plane where the trinangle face belong to
193     TPointIds aPointIds;
194     aPointIds.insert(aNewPts[0]);
195     aPointIds.insert(aNewPts[1]);
196     aPointIds.insert(aNewPts[2]);
197
198     // To get know, if the points of the trinagle were already observed
199     bool anIsObserved = aFace2PointIds.find(aPointIds) == aFace2PointIds.end();
200     //cout<<"\taFaceId = "<<aFaceId<<"; anIsObserved = "<<anIsObserved;
201     //cout<<"; aNewPts = {"<<aNewPts[0]<<", "<<aNewPts[1]<<", "<<aNewPts[2]<<"}\n";
202     
203     if(!anIsObserved){
204       // To get coordinates of the points of the traingle face
205       vtkFloatingPointType aCoord[3][3];
206       aPoints->GetPoint(aNewPts[0],aCoord[0]);
207       aPoints->GetPoint(aNewPts[1],aCoord[1]);
208       aPoints->GetPoint(aNewPts[2],aCoord[2]);
209       
210       // To calculate plane normal
211       vtkFloatingPointType aVector01[3] = { aCoord[1][0] - aCoord[0][0],
212                                             aCoord[1][1] - aCoord[0][1],
213                                             aCoord[1][2] - aCoord[0][2] };
214       
215       vtkFloatingPointType aVector02[3] = { aCoord[2][0] - aCoord[0][0],
216                                             aCoord[2][1] - aCoord[0][1],
217                                             aCoord[2][2] - aCoord[0][2] };
218       
219       // To calculate the normal for the triangle
220       vtkFloatingPointType aNormal[3];
221       vtkMath::Cross(aVector02,aVector01,aNormal);
222       
223       vtkMath::Normalize(aNormal);
224       
225       // To calculate what points belong to the plane
226       // To calculate bounds of the point set
227       vtkFloatingPointType aCenter[3] = {0.0, 0.0, 0.0};
228       {
229         TPointIds::const_iterator anIter = anInitialPointIds.begin();
230         TPointIds::const_iterator anEndIter = anInitialPointIds.end();
231         for(; anIter != anEndIter; anIter++){
232           vtkFloatingPointType aPntCoord[3];
233           vtkIdType aPntId = *anIter;
234           aPoints->GetPoint(aPntId,aPntCoord);
235           vtkFloatingPointType aDist = vtkPlane::DistanceToPlane(aPntCoord,aNormal,aCoord[0]);
236           //cout<<"\t\taPntId = "<<aPntId<<" {"<<aPntCoord[0]<<", "<<aPntCoord[1]<<", "<<aPntCoord[2]<<"}; aDist = "<<aDist<<"\n";
237           if(fabs(aDist) < aDistEps){
238             aPointIds.insert(aPntId);
239             aCenter[0] += aPntCoord[0];
240             aCenter[1] += aPntCoord[1];
241             aCenter[2] += aPntCoord[2];
242           }
243         }
244         int aNbPoints = aPointIds.size();
245         aCenter[0] /= aNbPoints;
246         aCenter[1] /= aNbPoints;
247         aCenter[2] /= aNbPoints;
248       }
249       
250       //To sinchronize orientation of the cell and its face
251       vtkFloatingPointType aVectorC[3] = { aCenter[0] - aCellCenter[0],
252                                            aCenter[1] - aCellCenter[1],
253                                            aCenter[2] - aCellCenter[2] };
254       vtkMath::Normalize(aVectorC);
255       
256       vtkFloatingPointType aDot = vtkMath::Dot(aNormal,aVectorC);
257       //cout<<"\t\taNormal = {"<<aNormal[0]<<", "<<aNormal[1]<<", "<<aNormal[2]<<"}";
258       //cout<<"; aVectorC = {"<<aVectorC[0]<<", "<<aVectorC[1]<<", "<<aVectorC[2]<<"}\n";
259       //cout<<"\t\taDot = "<<aDot<<"\n";
260       if(aDot > 0){
261         aNormal[0] = -aNormal[0];
262         aNormal[1] = -aNormal[1];
263         aNormal[2] = -aNormal[2];
264       }
265       
266       // To calculate the primary direction for point set
267       vtkFloatingPointType aVector0[3] = { aCoord[0][0] - aCenter[0],
268                                            aCoord[0][1] - aCenter[1],
269                                            aCoord[0][2] - aCenter[2] };
270       vtkMath::Normalize(aVector0);
271       
272       //cout<<"\t\taCenter = {"<<aCenter[0]<<", "<<aCenter[1]<<", "<<aCenter[2]<<"}";
273       //cout<<"; aVector0 = {"<<aVector0[0]<<", "<<aVector0[1]<<", "<<aVector0[2]<<"}\n";
274       
275       // To calculate the set of points by face those that belong to the plane
276       TFace2PointIds aRemoveFace2PointIds;
277       {
278         TFace2PointIds::const_iterator anIter = aFace2PointIds.begin();
279         TFace2PointIds::const_iterator anEndIter = aFace2PointIds.end();
280         for(; anIter != anEndIter; anIter++){
281           const TPointIds& anIds = *anIter;
282           TPointIds anIntersection;
283           std::set_intersection(aPointIds.begin(),aPointIds.end(),
284                                 anIds.begin(),anIds.end(),
285                                 std::inserter(anIntersection,anIntersection.begin()));
286           
287           if(anIntersection == anIds){
288             aRemoveFace2PointIds.insert(anIds);
289           }
290         }
291       }
292       
293       // To remove from the set of points by face those that belong to the plane
294       {
295         TFace2PointIds::const_iterator anIter = aRemoveFace2PointIds.begin();
296         TFace2PointIds::const_iterator anEndIter = aRemoveFace2PointIds.end();
297         for(; anIter != anEndIter; anIter++){
298           const TPointIds& anIds = *anIter;
299           aFace2PointIds.erase(anIds);
300         }
301       }
302       
303       // To sort the planar set of the points accrding to the angle
304       {
305         typedef std::map<vtkFloatingPointType,vtkIdType> TSortedPointIds;
306         TSortedPointIds aSortedPointIds;
307         
308         TPointIds::const_iterator anIter = aPointIds.begin();
309         TPointIds::const_iterator anEndIter = aPointIds.end();
310         for(; anIter != anEndIter; anIter++){
311           vtkFloatingPointType aPntCoord[3];
312           vtkIdType aPntId = *anIter;
313           aPoints->GetPoint(aPntId,aPntCoord);
314           vtkFloatingPointType aVector[3] = { aPntCoord[0] - aCenter[0],
315                                               aPntCoord[1] - aCenter[1],
316                                               aPntCoord[2] - aCenter[2] };
317           vtkMath::Normalize(aVector);
318           
319           vtkFloatingPointType aCross[3];
320           vtkMath::Cross(aVector,aVector0,aCross);
321           bool aGreaterThanPi = vtkMath::Dot(aCross,aNormal) < 0;
322           vtkFloatingPointType aCosinus = vtkMath::Dot(aVector,aVector0);
323           if(aCosinus > 1.0)
324             aCosinus = 1.0;
325           if(aCosinus < -1.0)
326             aCosinus = -1.0;
327           static vtkFloatingPointType a2Pi = 2.0 * vtkMath::Pi();
328           vtkFloatingPointType anAngle = acos(aCosinus);
329           //cout<<"\t\t\taPntId = "<<aPntId<<" {"<<aPntCoord[0]<<", "<<aPntCoord[1]<<", "<<aPntCoord[2]<<"}";
330           //cout<<"; aGreaterThanPi = "<<aGreaterThanPi<<"; aCosinus = "<<aCosinus<<"; anAngle = "<<anAngle<<"\n";
331           if(aGreaterThanPi){
332             anAngle = a2Pi - anAngle;
333             //cout<<"\t\t\t\tanAngle = "<<anAngle<<"\n";
334           }
335           aSortedPointIds[anAngle] = aPntId;
336         }
337
338         if(!aSortedPointIds.empty()){
339           int aNumFacePts = aSortedPointIds.size();
340           ::TConnectivities aConnectivities(aNumFacePts);
341           TSortedPointIds::const_iterator anIter = aSortedPointIds.begin();
342           TSortedPointIds::const_iterator anEndIter = aSortedPointIds.end();
343           for(vtkIdType anId = 0; anIter != anEndIter; anIter++, anId++){
344             vtkIdType aPntId = anIter->second;
345             aConnectivities[anId] = GetConnectivity(aPntId);
346           }
347           aPolygons.push_back(::TPolygon(aConnectivities,aCenter,aNormal));
348         }
349       }
350     }
351   }
352   
353   if(aPolygons.empty())
354     return true;
355
356   // To check, whether the polygons give a convex polyhedron or not
357   if(theIsCheckConvex){
358     int aNbPolygons = aPolygons.size();
359     for (int aPolygonId = 0; aPolygonId < aNbPolygons; aPolygonId++) {
360       ::TPolygon& aPolygon = aPolygons[aPolygonId];
361       vtkFloatingPointType* aNormal = aPolygon.myNormal;
362       vtkFloatingPointType* anOrigin = aPolygon.myOrigin;
363       //cout<<"\taPolygonId = "<<aPolygonId<<"\n";
364       //cout<<"\t\taNormal = {"<<aNormal[0]<<", "<<aNormal[1]<<", "<<aNormal[2]<<"}";
365       //cout<<"; anOrigin = {"<<anOrigin[0]<<", "<<anOrigin[1]<<", "<<anOrigin[2]<<"}\n";
366       for(vtkIdType aPntId = 0; aPntId < aNumPts; aPntId++){
367         vtkFloatingPointType aPntCoord[3];
368         vtkIdType anId = GetPointId(aPntId);
369         aPoints->GetPoint(anId,aPntCoord);
370         vtkFloatingPointType aDist = vtkPlane::Evaluate(aNormal,anOrigin,aPntCoord);
371         //cout<<"\t\taPntId = "<<anId<<" {"<<aPntCoord[0]<<", "<<aPntCoord[1]<<", "<<aPntCoord[2]<<"}; aDist = "<<aDist<<"\n";
372         if(aDist < -aDistEps)
373           return false;
374       }
375     }
376   }
377
378
379   // To pass resulting set of the polygons to the output
380   {
381     int aNbPolygons = aPolygons.size();
382     for (int aPolygonId = 0; aPolygonId < aNbPolygons; aPolygonId++) {
383       ::TPolygon& aPolygon = aPolygons[aPolygonId];
384       TConnectivities& aConnectivities = aPolygon.myConnectivities;
385       int aNbPoints = aConnectivities.size();
386       vtkIdType aNewCellId = theOutput->InsertNextCell(VTK_POLYGON,aNbPoints,&aConnectivities[0]);
387       if(theStoreMapping)
388         theVTK2ObjIds.push_back(theCellId);
389       theOutputCD->CopyData(thInputCD,theCellId,aNewCellId);
390     }
391   }
392
393   //cout<<"\tTriangulator - Ok\n";
394   return true;
395 }
396
397 /*!
398   Constructor
399 */
400 VTKViewer_OrderedTriangulator
401 ::VTKViewer_OrderedTriangulator():
402   myCell(vtkGenericCell::New())
403 {}
404
405 /*!
406   Destructor
407 */
408 VTKViewer_OrderedTriangulator
409 ::~VTKViewer_OrderedTriangulator()
410 {
411   myCell->Delete();
412 }
413
414 vtkPoints*
415 VTKViewer_OrderedTriangulator
416 ::InitPoints()
417 {
418   myInput->GetCell(myCellId,myCell);
419   return myInput->GetPoints();
420 }
421
422 vtkIdType 
423 VTKViewer_OrderedTriangulator
424 ::GetNbOfPoints()
425 {
426   return myCell->GetNumberOfPoints();
427 }
428
429 vtkIdType 
430 VTKViewer_OrderedTriangulator
431 ::GetPointId(vtkIdType thePointId)
432 {
433   return myCell->GetPointId(thePointId);
434 }
435
436 vtkFloatingPointType 
437 VTKViewer_OrderedTriangulator
438 ::GetCellLength()
439 {
440   return sqrt(myCell->GetLength2());
441 }
442
443 vtkIdType 
444 VTKViewer_OrderedTriangulator
445 ::GetNumFaces()
446 {
447   return myCell->GetNumberOfFaces();
448 }
449
450 vtkCell*
451 VTKViewer_OrderedTriangulator
452 ::GetFace(vtkIdType theFaceId)
453 {
454   return myCell->GetFace(theFaceId);
455 }
456
457 void 
458 VTKViewer_OrderedTriangulator
459 ::GetCellNeighbors(vtkIdType theCellId,
460                    vtkCell* theFace,
461                    vtkIdList* theCellIds)
462 {
463   vtkIdList *anIdList = theFace->PointIds;  
464   myInput->GetCellNeighbors(theCellId, anIdList, theCellIds);
465 }
466
467 vtkIdType 
468 VTKViewer_OrderedTriangulator
469 ::GetConnectivity(vtkIdType thePntId)
470 {
471   return thePntId;
472 }
473
474 /*!
475   Constructor
476 */
477 VTKViewer_DelaunayTriangulator
478 ::VTKViewer_DelaunayTriangulator():
479   myUnstructuredGrid(vtkUnstructuredGrid::New()),
480   myGeometryFilter(vtkGeometryFilter::New()),
481   myDelaunay3D(vtkDelaunay3D::New()),
482   myFaceIds(vtkIdList::New()),
483   myPoints(vtkPoints::New()),
484   myPolyData(NULL),
485   myPointIds(NULL)
486 {
487   myDelaunay3D->SetInput(myUnstructuredGrid);
488   myGeometryFilter->SetInput(myDelaunay3D->GetOutput());
489 }
490
491
492
493 /*!
494   Destructor
495 */
496 VTKViewer_DelaunayTriangulator
497 ::~VTKViewer_DelaunayTriangulator()
498 {
499   myUnstructuredGrid->Delete();
500   myGeometryFilter->Delete();
501   myDelaunay3D->Delete();
502   myFaceIds->Delete();
503   myPoints->Delete();
504 }
505
506
507 vtkPoints* 
508 VTKViewer_DelaunayTriangulator
509 ::InitPoints()
510 {
511   myUnstructuredGrid->Initialize();
512   myUnstructuredGrid->Allocate();
513   myUnstructuredGrid->SetPoints(myPoints);
514
515   vtkIdType aNumPts;
516   myInput->GetCellPoints(myCellId,aNumPts,myPointIds); 
517   {
518     vtkFloatingPointType aPntCoord[3];
519     myPoints->SetNumberOfPoints(aNumPts);
520     vtkPoints *anInputPoints = myInput->GetPoints();
521     for (int aPntId = 0; aPntId < aNumPts; aPntId++) {
522       anInputPoints->GetPoint(myPointIds[aPntId],aPntCoord);
523       myPoints->SetPoint(aPntId,aPntCoord);
524     }
525   }
526
527   myGeometryFilter->Update();
528   myPolyData = myGeometryFilter->GetOutput();
529
530   return myPoints;
531 }
532
533 vtkIdType 
534 VTKViewer_DelaunayTriangulator
535 ::GetNbOfPoints()
536 {
537   return myPoints->GetNumberOfPoints();
538 }
539
540 vtkIdType 
541 VTKViewer_DelaunayTriangulator
542 ::GetPointId(vtkIdType thePointId)
543 {
544   return thePointId;
545 }
546
547 vtkFloatingPointType 
548 VTKViewer_DelaunayTriangulator
549 ::GetCellLength()
550 {
551   return myPolyData->GetLength();
552 }
553
554 vtkIdType 
555 VTKViewer_DelaunayTriangulator
556 ::GetNumFaces()
557 {
558   return myPolyData->GetNumberOfCells();
559 }
560
561 vtkCell*
562 VTKViewer_DelaunayTriangulator
563 ::GetFace(vtkIdType theFaceId)
564 {
565   return myPolyData->GetCell(theFaceId);
566 }
567
568 void 
569 VTKViewer_DelaunayTriangulator
570 ::GetCellNeighbors(vtkIdType theCellId,
571                    vtkCell* theFace,
572                    vtkIdList* theCellIds)
573 {
574   myFaceIds->Reset();
575   vtkIdList *anIdList = theFace->PointIds;  
576   myFaceIds->InsertNextId(myPointIds[anIdList->GetId(0)]);
577   myFaceIds->InsertNextId(myPointIds[anIdList->GetId(1)]);
578   myFaceIds->InsertNextId(myPointIds[anIdList->GetId(2)]);
579
580   myInput->GetCellNeighbors(theCellId, myFaceIds, theCellIds);
581 }
582
583
584 vtkIdType 
585 VTKViewer_DelaunayTriangulator
586 ::GetConnectivity(vtkIdType thePntId)
587 {
588   return myPointIds[thePntId];
589 }