1 // This library is distributed in the hope that it will be useful,
2 // but WITHOUT ANY WARRANTY; without even the implied warranty of
3 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4 // Lesser General Public License for more details.
6 // You should have received a copy of the GNU Lesser General Public
7 // License along with this library; if not, write to the Free Software
8 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
12 #include "VTKViewer_ConvexTool.h"
14 #include <vtkUnstructuredGrid.h>
15 #include <vtkTriangle.h>
16 #include <vtkConvexPointSet.h>
24 typedef std::set<vtkIdType> TUIDS; // unique ids
25 typedef std::map<vtkIdType,TUIDS> TPTOIDS; // id points -> unique ids
30 static float FACE_ANGLE_TOLERANCE=1.5;
33 static int MYDEBUG = 0;
35 static int MYDEBUG = 0;
38 /*! \fn static void GetCenter(vtkUnstructuredGrid* theGrid,TCell theptIds,float *center)
39 * \brief Calculation of geometry center.
40 * \param theGrid - vtkUnstructuredGrid cell.
41 * \param theptIds - point ids.
42 * \retval center - output array[3] with coordinates of geometry center.
44 static void GetCenter(vtkUnstructuredGrid* theGrid,TCell theptIds,float *center)
47 center[0] = center[1] = center[2] = 0.0;
49 int numIds=theptIds.size();
51 // get the center of the cell
52 for (int i=0; i < numIds; i++)
54 p = theGrid->GetPoint(theptIds[i]);
55 for (int j=0; j < 3; j++)
60 for (int j=0; j<3; j++)
66 /*! \fn static void ReverseIds(TCell &theIds)
68 * \param theIds - points ids.
69 * \retval theIds - example input:(1,2,3,4) -> output:(4,3,2,1)
71 static void ReverseIds(TCell &theIds)
75 vtkIdType npts=theIds.size();
77 for(i=0;i<(npts/2);i++){
79 theIds[i] = theIds[npts-i-1];
80 theIds[npts-i-1] = tmp;
84 /*! \fn void GetFriends(const TPTOIDS p2faces,const TCellArray f2points,TPTOIDS& face2face_output)
85 * \brief Caclulation of connected faces (faceId -> (faceId1,faceId2, ...))
86 * \param p2faces - point to faces ids map.
87 * \param f2points - faces to points ids map.
88 * \retval face2face_output - faces to faces ids map.
90 void GetFriends(const TPTOIDS p2faces,const TCellArray f2points,TPTOIDS& face2face_output)
92 TCellArray::const_iterator f2pIter = f2points.begin();
94 for( ; f2pIter!=f2points.end() ; f2pIter++ ){
95 vtkIdType faceId = f2pIter->first;
96 TCell face_points = f2pIter->second;
97 int nb_face_points = face_points.size();
101 TPTOIDS::const_iterator faces1;
102 TPTOIDS::const_iterator faces2;
104 id1 = face_points[0];
105 faces1 = p2faces.find(id1);
109 for(int i=1 ; i<nb_face_points ; i++ ){
111 id2 = face_points[i];
113 faces2 = p2faces.find(id2);
115 std::set_intersection(faces1->second.begin(), faces1->second.end(), faces2->second.begin(), faces2->second.end(),
116 std::inserter(output_faces,output_faces.begin()));
121 id1 = face_points[0];
122 faces1 = p2faces.find(id1);
123 std::set_intersection(faces1->second.begin(), faces1->second.end(), faces2->second.begin(), faces2->second.end(),
124 std::inserter(output_faces,output_faces.begin()));
126 output_faces.erase(faceId); // erase the face id for which we found friends
129 cout << "fId[" << faceId <<"]: ";
130 std::copy(output_faces.begin(), output_faces.end(), std::ostream_iterator<vtkIdType>(cout, " "));
134 face2face_output[faceId] = output_faces;
138 /*! \fn bool IsConnectedFacesOnOnePlane( vtkUnstructuredGrid* theGrid,vtkIdType theFId1, vtkIdType theFId2,TUIDS FpIds1, TUIDS FpIds2 )
139 * \brief Check is connected faces on one plane.
140 * \param theGrid - vtkUnstructuredGrid
141 * \param theFId1 - id of first face
142 * \param theFId2 - id of second face
143 * \param FpIds1 - first face points ids.
144 * \param FpIds2 - second face points ids.
145 * \return TRUE if two faces on one plane, else FALSE.
147 bool IsConnectedFacesOnOnePlane( vtkUnstructuredGrid* theGrid,
148 vtkIdType theFId1, vtkIdType theFId2,
149 TUIDS FpIds1, TUIDS FpIds2 )
153 std::set_intersection(FpIds1.begin(), FpIds1.end(), FpIds2.begin(), FpIds2.end(),
154 std::inserter(common_ids,common_ids.begin()));
156 /* Number of common ids = 2 (A1,A2)
159 _ _ _ _ _ _ _ _ _ vectors:
168 |_ _ _ _ _/ \_ _ _ _ _|
172 TUIDS::iterator common_iter = common_ids.begin();
173 if(common_ids.size() == 2){
174 TUIDS::iterator loc_id1_0 = FpIds1.find(*(common_iter));
176 TUIDS::iterator loc_id1_1 = FpIds1.find(*(common_iter));
178 TUIDS::iterator loc_id2_0 = FpIds1.begin();
179 TUIDS::iterator loc_id2_1 = FpIds2.begin();
181 vtkIdType A1 = *loc_id1_0;
182 vtkIdType A2 = *loc_id1_1;
186 for(;loc_id2_0!=FpIds1.end();loc_id2_0++)
187 if(*loc_id2_0 != A1 && *loc_id2_0!= A2){
191 for(;loc_id2_1!=FpIds2.end();loc_id2_1++)
192 if(*loc_id2_1 != A1 && *loc_id2_1!= A2){
196 if(MYDEBUG) cout <<endl;
197 if(MYDEBUG) cout << "FId_1="<<theFId1<<" FId_2="<<theFId2<<endl;
198 if(MYDEBUG) cout << " A1="<<A1<<" A2="<<A2<<" B1="<<B1<<" C1="<<C1<<" ->";
200 float v1[3],v2[3],v3[3];
201 p[0] = theGrid->GetPoint(A1);
202 p[1] = theGrid->GetPoint(A2);
203 p[2] = theGrid->GetPoint(B1);
204 p[3] = theGrid->GetPoint(C1);
206 for(int i=0;i<3;i++){
207 v1[i] = p[1][i] - p[0][i];
208 v2[i] = p[2][i] - p[0][i];
209 v3[i] = p[3][i] - p[0][i];
214 vtkMath::Cross(v2,v1,vec_b1);
216 vtkMath::Cross(v1,v3,vec_b2);
218 float b1 = vtkMath::Norm(vec_b1);
220 float b2 = vtkMath::Norm(vec_b2);
221 float aCos = vtkMath::Dot(vec_b1,vec_b2)/(b1*b2);
224 angle = aCos>=1.0 ? 0.0 : 180*acosf(aCos)/vtkMath::Pi();
226 if( angle <= FACE_ANGLE_TOLERANCE)
229 for(int k=0;k<4;k++){
231 for(int j=0;j<2;j++){
232 cout << p[k][j] << ",";
234 cout << p[k][2] << ") ";
236 cout << "angle="<<angle<<" status="<<status<<endl;
239 } else if (common_ids.size() >2){
240 // not implemented yet
241 if(MYDEBUG) cout << "Warning! VTKViewer_ConvexTool::IsConnectedFacesOnOnePlane()";
243 // one or no connection ... continue
249 /*! \fn void GetAllFacesOnOnePlane( TPTOIDS theFaces, vtkIdType faceId,TUIDS &new_faces, TCell &new_faces_v2 )
250 * \brief Calculate faces which on one plane.
254 * \param new_faces_v2 -
256 void GetAllFacesOnOnePlane( TPTOIDS theFaces, vtkIdType faceId,
257 TUIDS &new_faces, TCell &new_faces_v2 )
259 if (new_faces.find(faceId) != new_faces.end()) return;
261 new_faces.insert(new_faces.begin(),faceId);
262 new_faces_v2.push_back(faceId);
264 TPTOIDS::const_iterator aIter1 = theFaces.find(faceId);
265 if(aIter1!=theFaces.end()){
266 TUIDS::const_iterator aIter2 = (aIter1->second).begin();
267 for(;aIter2!=(aIter1->second).end();aIter2++){
268 if (new_faces.find(*aIter2) != new_faces.end()) continue;
269 GetAllFacesOnOnePlane(theFaces,*aIter2,
270 new_faces,new_faces_v2); // recurvise
276 /*! \fn void GetSumm(TCell v1,TCell v2,TCell &output)
277 * \brief Gluing two faces (gluing points ids)
278 * \param v1 - first face
279 * \param v2 - second face
280 * \param output - output face.
282 void GetSumm(TCell v1,TCell v2,TCell &output)
286 if(MYDEBUG) cout << "========================================="<<endl;
287 if(MYDEBUG) cout << "v1:";
288 if(MYDEBUG) std::copy(v1.begin(), v1.end(), std::ostream_iterator<vtkIdType>(cout, " "));
289 if(MYDEBUG) cout << "\tv2:";
290 if(MYDEBUG) std::copy(v2.begin(), v2.end(), std::ostream_iterator<vtkIdType>(cout, " "));
291 if(MYDEBUG) cout << endl;
294 std::copy(v1.begin(), v1.end(), std::inserter(v1_set,v1_set.begin()));
296 std::copy(v2.begin(), v2.end(), std::inserter(v2_set,v2_set.begin()));
297 TUIDS tmpIntersection;
298 std::set_intersection(v1_set.begin(),v1_set.end(),v2_set.begin(),v2_set.end(), std::inserter(tmpIntersection,tmpIntersection.begin()));
299 if(MYDEBUG) std::copy(tmpIntersection.begin(),tmpIntersection.end(), std::ostream_iterator<vtkIdType>(cout, " "));
300 if(MYDEBUG) cout << endl;
302 if(tmpIntersection.size() < 2)
303 if(MYDEBUG) cout << __FILE__ << "[" << __LINE__ << "]: Warning ! Wrong ids" << endl;
305 TCell::iterator v1_iter = v1.begin();
307 for(;v1_iter!=v1.end();v1_iter++){
309 vtkIdType curr_id = *v1_iter;
311 output.push_back(curr_id);
313 if(tmpIntersection.find(curr_id) != tmpIntersection.end()){
314 TCell::iterator v1_iter_tmp;
315 v1_iter_tmp = v1_iter;
318 if(v1_iter==v1.end()) v1_iter=v1.begin();
322 if(tmpIntersection.find(curr_id) != tmpIntersection.end()){
323 TCell::iterator v2_iter = v2.begin();
324 for(;v2_iter!=v2.end();v2_iter++){
325 vtkIdType v2_id = *v2_iter;
326 if(tmpIntersection.find(v2_id) == tmpIntersection.end())
327 output.push_back(v2_id);
331 v1_iter = v1_iter_tmp;
337 if(MYDEBUG) cout << "Result: " ;
338 if(MYDEBUG) std::copy(output.begin(),output.end(),std::ostream_iterator<vtkIdType>(cout, " "));
339 if(MYDEBUG) cout << endl;
342 void GetPolygonalFaces(vtkUnstructuredGrid* theGrid,int cellId,TCellArray &outputCellArray)
344 if (theGrid->GetCellType(cellId) == VTK_CONVEX_POINT_SET){
345 // get vtkCell type = VTK_CONVEX_POINT_SET
346 if(vtkConvexPointSet* convex = static_cast<vtkConvexPointSet*>(theGrid->GetCell(cellId))){
348 float convex_center[3]; // convex center point coorinat
349 int aNbFaces = convex->GetNumberOfFaces();
350 int numPts = convex->GetNumberOfPoints();
352 TPTOIDS p2faces; // key=pointId , value facesIds set
354 for(int i=0;i<numPts;i++)
355 convex_ids.push_back(convex->GetPointId(i));
357 GetCenter(theGrid,convex_ids,convex_center);
359 for (vtkIdType faceId=0; faceId < aNbFaces; faceId++){
360 vtkCell *aFace = convex->GetFace(faceId);
361 int numFacePts = aFace->GetNumberOfPoints();
365 for(i=0;i<numFacePts;i++)
366 aIds.push_back(aFace->GetPointId(i));
368 float v_a[3],v_b[3],v_convex2face[3]; // vectors
369 float *id_0,*id_1,*id_n;
370 /*=============================================
372 _ / id_n | v_b {id_0,id_n}
384 ============================================*/
385 id_0 = theGrid->GetPoint(aIds[0]);
386 id_1 = theGrid->GetPoint(aIds[1]);
387 id_n = theGrid->GetPoint(aIds[numFacePts-1]);
390 v_a[i] = id_1[i] - id_0[i];
391 v_b[i] = id_n[i] - id_0[i];
392 v_convex2face[i] = id_0[i] - convex_center[i];
395 if (vtkMath::Determinant3x3(v_a,v_b,v_convex2face) < 0){
399 for(i=0;i<(int)aIds.size();i++){
400 TUIDS &acell = p2faces[aIds[i]];
401 acell.insert(faceId);
404 f2points[faceId] = aIds;
409 GetFriends(p2faces,f2points,face2face);
413 // copy TCellArray::f2points to TPTOIDS::face2points
414 for(TCellArray::iterator f2points_iter=f2points.begin();
415 f2points_iter!=f2points.end();
419 for(TCell::iterator points_iter=(f2points_iter->second).begin();
420 points_iter!=(f2points_iter->second).end();
422 tmp.insert(*points_iter);
424 face2points[f2points_iter->first] = tmp;
428 TPTOIDS new_face2faces; // which connected and in one plane
430 TPTOIDS::const_iterator aF2FIter = face2face.begin();
431 for(;aF2FIter!=face2face.end();aF2FIter++){
432 vtkIdType f_key = aF2FIter->first;
433 TUIDS &faces = new_face2faces[f_key];
434 //faces.insert(f_key);
435 TUIDS f_friends = aF2FIter->second;
436 TUIDS::const_iterator a_friends_iter = f_friends.begin();
437 for(;a_friends_iter!=f_friends.end();a_friends_iter++){
438 vtkIdType friend_id = *a_friends_iter;
439 if( IsConnectedFacesOnOnePlane(theGrid,f_key,friend_id,
440 (face2points.find(f_key))->second,
441 (face2points.find(friend_id))->second)){
442 faces.insert(friend_id);
445 } // end a_friends_iter
450 TPTOIDS::const_iterator new_face2face_iter = new_face2faces.begin();
451 cout << "Connected faces and on plane:" << endl;
452 for(;new_face2face_iter!=new_face2faces.end();new_face2face_iter++){
453 cout << "Group ["<<new_face2face_iter->first<<"] :";
454 TUIDS::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
455 for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++)
456 cout << " " << *new_faces_iter ;
461 TPTOIDS output_newid2face;
462 TCellArray output_newid2face_v2;
465 TUIDS already_in_tmp;
467 TPTOIDS::const_iterator new_face2face_iter = new_face2faces.begin();
468 for(;new_face2face_iter!=new_face2faces.end();new_face2face_iter++){
469 if(already_in.find(new_face2face_iter->first) != already_in.end())
471 if(new_face2face_iter->second.size() > 1)
474 TCell &tmp_v2 = output_newid2face_v2[k];
475 tmp_v2.push_back(new_face2face_iter->first);
476 already_in.insert(new_face2face_iter->first);
478 TUIDS::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
479 for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++){
480 if(already_in.find(*new_faces_iter) != already_in.end()) continue;
481 already_in.insert(*new_faces_iter);
483 already_in_tmp.clear();
484 already_in_tmp.insert(new_face2face_iter->first);
486 TUIDS &tmp = output_newid2face[k];
487 GetAllFacesOnOnePlane(new_face2faces,*new_faces_iter,
488 already_in_tmp,tmp_v2);
490 for(TUIDS::const_iterator aIter=already_in_tmp.begin();
491 aIter!=already_in_tmp.end();
494 already_in.insert(*aIter);
503 cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"<<endl;
505 TPTOIDS::const_iterator new_face2face_iter = output_newid2face.begin();
506 for(;new_face2face_iter!=output_newid2face.end();new_face2face_iter++){
507 cout << "Group ["<<new_face2face_iter->first<<"] :";
508 TUIDS::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
509 for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++)
510 cout << " " << *new_faces_iter ;
514 cout << "++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++"<<endl;
515 cout << "++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++"<<endl;
516 cout << "+++++++++++++++++++++++ ++ ++ ++++++++++++++++++++++++++++"<<endl;
517 cout << "+++++++++++++++++++++++++ ++++++++++++++++++++++++++++++"<<endl;
518 cout << "++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++"<<endl;
520 TCellArray::const_iterator new_face2face_iter = output_newid2face_v2.begin();
521 for(;new_face2face_iter!=output_newid2face_v2.end();new_face2face_iter++){
522 cout << "Group ["<<new_face2face_iter->first<<"] :";
523 TCell::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
524 for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++)
525 cout << " " << *new_faces_iter ;
530 TCellArray output_new_face2ids;
532 // TPTOIDS::const_iterator new_face2face_iter = output_newid2face.begin();
533 // for(;new_face2face_iter!=output_newid2face.end();new_face2face_iter++){
535 // vtkIdType new_faceId = new_face2face_iter->first;
536 // TUIDS::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
537 // vtkIdType fId0 = *new_faces_iter;
538 // TCellArray::const_iterator pIds0_iter = f2points.find(fId0);
539 // TCell pIds0 = pIds0_iter->second;
540 // TCell &output = output_new_face2ids[new_faceId];
542 // if(new_face2face_iter->second.size() > 2 ){}
543 // for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++){
545 // vtkIdType faceId = *new_faces_iter;
546 // // find how much nodes in face (f2points)
547 // TCellArray::const_iterator pIds_iter = f2points.find(faceId);
548 // TCell pIds = pIds_iter->second;
550 // GetSumm(pIds0,pIds,output);
553 // } // end new_faces_iter
555 // } // new_face2face_iter
559 TCellArray::const_iterator new_face2face_iter = output_newid2face_v2.begin();
560 for(;new_face2face_iter!=output_newid2face_v2.end();new_face2face_iter++){
562 vtkIdType new_faceId = new_face2face_iter->first;
563 TCell::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
564 vtkIdType fId0 = *new_faces_iter;
565 TCellArray::const_iterator pIds0_iter = f2points.find(fId0);
566 TCell pIds0 = pIds0_iter->second;
567 TCell &output = output_new_face2ids[new_faceId];
569 if(new_face2face_iter->second.size() == 1 ){
570 TCellArray::const_iterator pIds_iter = f2points.find(fId0);
571 TCell pIds = pIds_iter->second;
575 for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++){
577 vtkIdType faceId = *new_faces_iter;
578 // find how much nodes in face (f2points)
579 TCellArray::const_iterator pIds_iter = f2points.find(faceId);
580 TCell pIds = pIds_iter->second;
582 GetSumm(pIds0,pIds,output);
585 } // end new_faces_iter
587 } // new_face2face_iter
591 cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"<<endl;
592 cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"<<endl;
593 cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"<<endl;
595 outputCellArray = output_new_face2ids;//f2points;