Salome HOME
updated copyright message
[modules/gui.git] / src / VTKViewer / VTKViewer_ConvexTool.cxx
index 3e22b42a6963b773550ef109bb9d32405b311375..62d3709ba38baa7b408a0d365226461c3bf31de5 100644 (file)
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+// Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 
 #include "VTKViewer_ConvexTool.h"
-
-#include <vtkUnstructuredGrid.h>
-#include <vtkTriangle.h>
-#include <vtkConvexPointSet.h>
-#include <vtkMath.h>
+#include "VTKViewer_GeometryFilter.h"
 
 #include <set>
-#include <iterator>
+#include <map>
 #include <algorithm>
-#include <math.h>
-
-static float FACE_ANGLE_TOLERANCE=1.5;
+#include <iterator>
 
-typedef std::set<vtkIdType> TUIDS; // unique ids 
-typedef std::map<vtkIdType,TUIDS> TPTOIDS; // id points -> unique ids
+#include <vtkUnstructuredGrid.h>
+#include <vtkGeometryFilter.h>
+#include <vtkDelaunay3D.h>
+#include <vtkGenericCell.h>
+#include <vtkPolyData.h>
+#include <vtkCellData.h>
+#include <vtkPoints.h>
+#include <vtkIdList.h>
+#include <vtkCell.h>
+#include <vtkPlane.h>
+#include <vtkMath.h>
+#include <vtkCellArray.h>
+#include <vtkTriangle.h>
+#include <vtkOrderedTriangulator.h>
 
-namespace CONVEX_TOOL
-{
 #ifdef _DEBUG_
-  static int MYDEBUG = 0;
+static int DEBUG_TRIA_EXECUTE = 0;
 #else
-  static int MYDEBUG = 0;
+static int DEBUG_TRIA_EXECUTE = 0;
 #endif
 
-static void GetCenter(vtkUnstructuredGrid* theGrid,TCell theptIds,float *center)
+namespace
 {
-  float *p;
-  center[0] = center[1] = center[2] = 0.0;
-  
-  int numIds=theptIds.size();
-
-  // get the center of the cell
-  for (int i=0; i < numIds; i++)
-    {
-      p = theGrid->GetPoint(theptIds[i]);
-      for (int j=0; j < 3; j++)
-       {
-         center[j] += p[j];
-       }
-    }
-  for (int j=0; j<3; j++)
+  typedef std::vector<vtkIdType> TConnectivities;
+
+  struct TPolygon
+  {
+    TConnectivities myConnectivities;
+    double myOrigin[3];
+    double myNormal[3];
+    TPolygon(const TConnectivities& theConnectivities,
+             double theOrigin[3],
+             double theNormal[3]):
+      myConnectivities(theConnectivities)
     {
-      center[j] /= numIds;
+      myOrigin[0] = theOrigin[0];
+      myOrigin[1] = theOrigin[1];
+      myOrigin[2] = theOrigin[2];
+
+      myNormal[0] = theNormal[0];
+      myNormal[1] = theNormal[1];
+      myNormal[2] = theNormal[2];
     }
+  };
+
+  typedef std::vector<TPolygon> TPolygons;
+}
+
+
+//----------------------------------------------------------------------------
+VTKViewer_Triangulator
+::VTKViewer_Triangulator():
+  myCellIds(vtkIdList::New()),
+  myPointIds(NULL),
+  myFaceIds(vtkIdList::New()),
+  myPoints(vtkPoints::New())
+{}
+
+
+//----------------------------------------------------------------------------
+VTKViewer_Triangulator
+::~VTKViewer_Triangulator()
+{
+  myCellIds->Delete();
+  myFaceIds->Delete();
+  myPoints->Delete();
 }
 
-static void ReverseIds(TCell &theIds)
+
+//----------------------------------------------------------------------------
+vtkPoints*
+VTKViewer_Triangulator
+::InitPoints(vtkUnstructuredGrid *theInput,
+             vtkIdType theCellId)
 {
-  int i;
-  vtkIdType tmp;
-  vtkIdType npts=theIds.size();
-
-  for(i=0;i<(npts/2);i++){
-    tmp = theIds[i];
-    theIds[i] = theIds[npts-i-1];
-    theIds[npts-i-1] = tmp;
+  myPoints->Reset();
+  myPoints->Modified(); // the VTK bug
+
+  vtkIdType aNumPts;
+  vtkIdType const *tmp;
+  theInput->GetCellPoints(theCellId, aNumPts, tmp);
+  myPointIds = const_cast<vtkIdType*>( tmp );
+  if ( aNumPts > 0 ) {
+    double anAbsoluteCoord[3];
+    myPoints->SetNumberOfPoints(aNumPts);
+    vtkPoints *anInputPoints = theInput->GetPoints();
+    for (auto aPntId = 0; aPntId < aNumPts; aPntId++) {
+      anInputPoints->GetPoint(myPointIds[aPntId], anAbsoluteCoord);
+      myPoints->SetPoint(aPntId, anAbsoluteCoord);
+    }
   }
+
+  return myPoints;
 }
 
-// caclulation of connected faces (faceId -> (faceId1,faceId2, ...))
-void GetFriends(const TPTOIDS p2faces,const TCellArray f2points,TPTOIDS& face2face_output)
+
+//----------------------------------------------------------------------------
+vtkIdType 
+VTKViewer_Triangulator
+::GetNbOfPoints()
 {
-  TCellArray::const_iterator f2pIter = f2points.begin();
+  return myPoints->GetNumberOfPoints();
+}
 
-  for( ; f2pIter!=f2points.end() ; f2pIter++ ){
-    vtkIdType faceId = f2pIter->first;
-    TCell face_points = f2pIter->second;
-    int nb_face_points = face_points.size();
-    
-    vtkIdType id1;
-    vtkIdType id2;
-    TPTOIDS::const_iterator faces1;
-    TPTOIDS::const_iterator faces2;
-    
-    id1 = face_points[0];
-    faces1 = p2faces.find(id1);
-    
-    TUIDS output_faces;
-      
-    for(int i=1 ; i<nb_face_points ; i++ ){
 
-      id2 = face_points[i];
+//----------------------------------------------------------------------------
+vtkIdType 
+VTKViewer_Triangulator
+::GetPointId(vtkIdType thePointId)
+{
+  return thePointId;
+}
 
-      faces2 = p2faces.find(id2);
-      
-      std::set_intersection(faces1->second.begin(), faces1->second.end(), faces2->second.begin(), faces2->second.end(),
-        std::inserter(output_faces,output_faces.begin()));
-      
-      id1 = id2;
-      faces1 = faces2;
-    }
-    id1 = face_points[0];
-    faces1 = p2faces.find(id1);
-    std::set_intersection(faces1->second.begin(), faces1->second.end(), faces2->second.begin(), faces2->second.end(),
-      std::inserter(output_faces,output_faces.begin()));
-    
-    output_faces.erase(faceId); // erase the face id for which we found friends
 
-    if(MYDEBUG){
-      cout << "fId[" << faceId <<"]: ";
-      std::copy(output_faces.begin(), output_faces.end(), std::ostream_iterator<vtkIdType>(cout, " "));
-      cout << endl;
-    }
-    
-    face2face_output[faceId] = output_faces;
-  }
+//----------------------------------------------------------------------------
+double 
+VTKViewer_Triangulator
+::GetCellLength()
+{
+  double aBounds[6];
+  myPoints->GetBounds(aBounds);
+
+  double aCoordDiff[3];
+  aCoordDiff[0] = (aBounds[1] - aBounds[0]);
+  aCoordDiff[1] = (aBounds[3] - aBounds[2]);
+  aCoordDiff[2] = (aBounds[5] - aBounds[4]);
+
+  return sqrt(aCoordDiff[0]*aCoordDiff[0] + 
+              aCoordDiff[1]*aCoordDiff[1] + 
+              aCoordDiff[2]*aCoordDiff[2]);
 }
 
-bool IsConnectedFacesOnOnePlane( vtkUnstructuredGrid* theGrid,
-                                 vtkIdType theFId1, vtkIdType theFId2,
-                                                        TUIDS FpIds1, TUIDS FpIds2 )
+
+//----------------------------------------------------------------------------
+void 
+VTKViewer_Triangulator
+::GetCellNeighbors(vtkUnstructuredGrid *theInput,
+                   vtkIdType theCellId,
+                   vtkCell* theFace,
+                   vtkIdList* theCellIds)
 {
-  bool status = false;
-  TUIDS common_ids;
-  std::set_intersection(FpIds1.begin(), FpIds1.end(), FpIds2.begin(), FpIds2.end(),
-                       std::inserter(common_ids,common_ids.begin()));
-  
-  /*           Number of common ids = 2 (A1,A2)
-              
-  
-                _ _ _ _ _      _ _ _ _    vectors:
-               |         \   /         |   v1 {A2,A1}
-                          \ /              v2 {A1,B1}
-               |           | A2        |   v3 {A1,C1}
-                          |               
-              |           |           |
-                          |
-              |           | A1        |
-                         / \
-              |_ _ _ _ _/   \_ _ _ _ _|
-              B2        B1   C1        C2
-
-   */
-  TUIDS::iterator common_iter = common_ids.begin();
-  if(common_ids.size() == 2){
-    TUIDS::iterator loc_id1_0 = FpIds1.find(*(common_iter));
-    common_iter++;
-    TUIDS::iterator loc_id1_1 = FpIds1.find(*(common_iter));
-
-    TUIDS::iterator loc_id2_0 = FpIds1.begin();
-    TUIDS::iterator loc_id2_1 = FpIds2.begin();
-
-    vtkIdType A1 = *loc_id1_0;
-    vtkIdType A2 = *loc_id1_1;
-    vtkIdType B1;
-    vtkIdType C1;
-
-    for(;loc_id2_0!=FpIds1.end();loc_id2_0++)
-      if(*loc_id2_0 != A1 && *loc_id2_0!= A2){
-       B1 = *loc_id2_0;
-       break;
-      }
-    for(;loc_id2_1!=FpIds2.end();loc_id2_1++)
-      if(*loc_id2_1 != A1 && *loc_id2_1!= A2){
-       C1 = *loc_id2_1;
-       break;
-      }
-    if(MYDEBUG) cout <<endl;
-    if(MYDEBUG) cout << "FId_1="<<theFId1<<" FId_2="<<theFId2<<endl;
-    if(MYDEBUG) cout << "   A1="<<A1<<" A2="<<A2<<" B1="<<B1<<" C1="<<C1<<" ->";
-    float *p[4];
-    float v1[3],v2[3],v3[3];
-    p[0] = theGrid->GetPoint(A1);
-    p[1] = theGrid->GetPoint(A2);
-    p[2] = theGrid->GetPoint(B1);
-    p[3] = theGrid->GetPoint(C1);
-
-    for(int i=0;i<3;i++){
-      v1[i] = p[1][i] - p[0][i];
-      v2[i] = p[2][i] - p[0][i];
-      v3[i] = p[3][i] - p[0][i];
-    }
-    
-    
-    float vec_b1[3];
-    vtkMath::Cross(v2,v1,vec_b1);
-    float vec_b2[3];
-    vtkMath::Cross(v1,v3,vec_b2);
+  myFaceIds->Reset();
+  vtkIdList *anIdList = theFace->PointIds;  
+  myFaceIds->InsertNextId(myPointIds[anIdList->GetId(0)]);
+  myFaceIds->InsertNextId(myPointIds[anIdList->GetId(1)]);
+  myFaceIds->InsertNextId(myPointIds[anIdList->GetId(2)]);
 
-    float b1 = vtkMath::Norm(vec_b1);
+  theInput->GetCellNeighbors(theCellId, myFaceIds, theCellIds);
+}
 
-    float b2 = vtkMath::Norm(vec_b2);
-    float aCos = vtkMath::Dot(vec_b1,vec_b2)/(b1*b2);
-    
-    float angle=90.0;
-    angle = aCos>=1.0 ? 0.0 : 180*acosf(aCos)/vtkMath::Pi();
-    
-    if( angle <= FACE_ANGLE_TOLERANCE)
-      status = true;
-    if (MYDEBUG){
-      for(int k=0;k<4;k++){
-       cout << " (";
-       for(int j=0;j<2;j++){
-         cout << p[k][j] << ",";
-       }
-       cout << p[k][2] << ")   ";
-      }
-      cout << "angle="<<angle<<" status="<<status<<endl;
-    }
-    
-  } else if (common_ids.size() >2){
-    // not implemented yet
-    if(MYDEBUG) cout << "Warning! VTKViewer_ConvexTool::IsConnectedFacesOnOnePlane()";
-  } else {
-    // one or no connection ... continue
-  }
-  
-  return status;
+
+//----------------------------------------------------------------------------
+vtkIdType 
+VTKViewer_Triangulator
+::GetConnectivity(vtkIdType thePntId)
+{
+  return myPointIds[thePntId];
 }
 
-void GetAllFacesOnOnePlane( TPTOIDS theFaces, vtkIdType faceId, 
-                            TUIDS &new_faces, TCell &new_faces_v2 )
+
+//----------------------------------------------------------------------------
+bool 
+VTKViewer_Triangulator
+::Execute(vtkUnstructuredGrid *theInput,
+          vtkCellData* thInputCD,
+          vtkIdType theCellId,
+          int theShowInside,
+          int theAllVisible,
+          int theAppendCoincident3D,
+          const char* theCellsVisibility,
+          vtkPolyData *theOutput,
+          vtkCellData* theOutputCD,
+          int theStoreMapping,
+          std::vector<vtkIdType>& theVTK2ObjIds,
+          std::vector< std::vector<vtkIdType> >& theDimension2VTK2ObjIds,
+          bool theIsCheckConvex)
 {
-  if (new_faces.find(faceId) != new_faces.end()) return;
-  
-  new_faces.insert(new_faces.begin(),faceId);
-  new_faces_v2.push_back(faceId);
-
-  TPTOIDS::const_iterator aIter1 = theFaces.find(faceId);
-  if(aIter1!=theFaces.end()){
-    TUIDS::const_iterator aIter2 = (aIter1->second).begin();
-    for(;aIter2!=(aIter1->second).end();aIter2++){
-      if (new_faces.find(*aIter2) != new_faces.end()) continue;
-      GetAllFacesOnOnePlane(theFaces,*aIter2,
-                           new_faces,new_faces_v2); // recurvise
+  vtkPoints *aPoints = InitPoints(theInput, theCellId);
+  vtkIdType aNumPts = GetNbOfPoints();
+  if(DEBUG_TRIA_EXECUTE) cout<<"Triangulator - aNumPts = "<<aNumPts<<"\n";
+
+  if(aNumPts == 0)
+    return true;
+
+  // To calculate the bary center of the cell
+  double aCellCenter[3] = {0.0, 0.0, 0.0};
+  {
+    double aPntCoord[3];
+    for (auto aPntId = 0; aPntId < aNumPts; aPntId++) {
+      aPoints->GetPoint(GetPointId(aPntId),aPntCoord);
+      if(DEBUG_TRIA_EXECUTE) cout<<"\taPntId = "<<GetPointId(aPntId)<<" {"<<aPntCoord[0]<<", "<<aPntCoord[1]<<", "<<aPntCoord[2]<<"}\n";
+      aCellCenter[0] += aPntCoord[0];
+      aCellCenter[1] += aPntCoord[1];
+      aCellCenter[2] += aPntCoord[2];
     }
+    aCellCenter[0] /= aNumPts;
+    aCellCenter[1] /= aNumPts;
+    aCellCenter[2] /= aNumPts;
   }
-  return;
-}
 
-void GetSumm(TCell v1,TCell v2,TCell &output)
-{
-  output.clear();
-
-  if(MYDEBUG) cout << "========================================="<<endl;
-  if(MYDEBUG) cout << "v1:";
-  if(MYDEBUG) std::copy(v1.begin(), v1.end(), std::ostream_iterator<vtkIdType>(cout, " "));
-  if(MYDEBUG) cout << "\tv2:";
-  if(MYDEBUG) std::copy(v2.begin(), v2.end(), std::ostream_iterator<vtkIdType>(cout, " "));
-  if(MYDEBUG) cout << endl;
-  
-  TUIDS v1_set;
-  std::copy(v1.begin(), v1.end(), std::inserter(v1_set,v1_set.begin()));
-  TUIDS v2_set;
-  std::copy(v2.begin(), v2.end(), std::inserter(v2_set,v2_set.begin()));
-  TUIDS tmpIntersection;
-  std::set_intersection(v1_set.begin(),v1_set.end(),v2_set.begin(),v2_set.end(), std::inserter(tmpIntersection,tmpIntersection.begin()));
-  if(MYDEBUG) std::copy(tmpIntersection.begin(),tmpIntersection.end(), std::ostream_iterator<vtkIdType>(cout, " "));
-  if(MYDEBUG) cout << endl;
-
-  if(tmpIntersection.size() < 2)
-    if(MYDEBUG) cout << __FILE__ << "[" << __LINE__ << "]: Warning ! Wrong ids" << endl;
+  double aCellLength = GetCellLength();
+  vtkIdType aNumFaces = GetNumFaces();
+
+  static double EPS = 1.0E-2;
+  double aDistEps = aCellLength/3.0 * EPS;
+  if(DEBUG_TRIA_EXECUTE) cout<<"\taNumFaces = "<<aNumFaces<<"; aCellLength = "<<aCellLength<<"; aDistEps = "<<aDistEps<<"\n";
+
+  // To initialize set of points that belong to the cell
+  typedef std::set<vtkIdType> TPointIds;
+  TPointIds anInitialPointIds;
+  for(vtkIdType aPntId = 0; aPntId < aNumPts; aPntId++)
+    anInitialPointIds.insert(GetPointId(aPntId));
   
-  TCell::iterator v1_iter = v1.begin();
+  // To initialize set of points by face that belong to the cell and backward
+  typedef std::set<vtkIdType> TFace2Visibility;
+  TFace2Visibility aFace2Visibility;
   
-  for(;v1_iter!=v1.end();v1_iter++){
-    
-    vtkIdType curr_id = *v1_iter;
-    
-    output.push_back(curr_id);
+  typedef std::set<TPointIds> TFace2PointIds;
+  TFace2PointIds aFace2PointIds;
+
+  for (auto aFaceId = 0; aFaceId < aNumFaces; aFaceId++) {
+    vtkCell* aFace = GetFace(aFaceId);
     
-    if(tmpIntersection.find(curr_id) != tmpIntersection.end()){
-      TCell::iterator v1_iter_tmp;
-      v1_iter_tmp = v1_iter;
-      v1_iter++;
-      if(v1_iter==v1.end()) v1_iter=v1.begin();
-
-      curr_id = *v1_iter;
-
-      if(tmpIntersection.find(curr_id) != tmpIntersection.end()){
-       TCell::iterator v2_iter = v2.begin();
-       for(;v2_iter!=v2.end();v2_iter++){
-         vtkIdType v2_id = *v2_iter;
-         if(tmpIntersection.find(v2_id) == tmpIntersection.end())
-           output.push_back(v2_id);
-       }
-      }
-      
-      v1_iter = v1_iter_tmp;
-      curr_id = *v1_iter;
+    GetCellNeighbors(theInput, theCellId, aFace, myCellIds);
+    bool process = myCellIds->GetNumberOfIds() <= 0 ? true : theAppendCoincident3D;
+    if((!theAllVisible && !theCellsVisibility[myCellIds->GetId(0)]) || 
+       myCellIds->GetNumberOfIds() <= 0 || theShowInside || process)
+    {
+      TPointIds aPointIds;
+      vtkIdList *anIdList = aFace->PointIds;  
+      aPointIds.insert(anIdList->GetId(0));
+      aPointIds.insert(anIdList->GetId(1));
+      aPointIds.insert(anIdList->GetId(2));
       
+      aFace2PointIds.insert(aPointIds);
+      aFace2Visibility.insert(aFaceId);
     }
   }
 
-  if(MYDEBUG) cout << "Result: " ;
-  if(MYDEBUG) std::copy(output.begin(),output.end(),std::ostream_iterator<vtkIdType>(cout, " "));
-  if(MYDEBUG) cout << endl;
-}
 
-void GetPolygonalFaces(vtkUnstructuredGrid* theGrid,int cellId,TCellArray &outputCellArray)
-{
-  if (theGrid->GetCellType(cellId) == VTK_CONVEX_POINT_SET){
-    // get vtkCell type = VTK_CONVEX_POINT_SET
-    if(vtkConvexPointSet* convex = static_cast<vtkConvexPointSet*>(theGrid->GetCell(cellId))){
-      TCellArray f2points;
-      float convex_center[3]; // convex center point coorinat
-      int aNbFaces = convex->GetNumberOfFaces();
-      int numPts = convex->GetNumberOfPoints();
-      TCell convex_ids;
-      TPTOIDS p2faces; // key=pointId , value facesIds set
+  ::TPolygons aPolygons;
+
+  for (auto aFaceId = 0; aFaceId < aNumFaces; aFaceId++) {
+    if(aFace2Visibility.find(aFaceId) == aFace2Visibility.end())
+      continue;
+
+    vtkCell* aFace = GetFace(aFaceId);
+
+    vtkIdList *anIdList = aFace->PointIds;
+    vtkIdType aNewPts[3] = {anIdList->GetId(0), anIdList->GetId(1), anIdList->GetId(2)};
+            
+    // To initialize set of points for the plane where the trinangle face belong to
+    TPointIds aPointIds;
+    aPointIds.insert(aNewPts[0]);
+    aPointIds.insert(aNewPts[1]);
+    aPointIds.insert(aNewPts[2]);
+
+    // To get know, if the points of the trinagle were already observed
+    bool anIsObserved = aFace2PointIds.find(aPointIds) == aFace2PointIds.end();
+    if(DEBUG_TRIA_EXECUTE) {
+      cout<<"\taFaceId = "<<aFaceId<<"; anIsObserved = "<<anIsObserved;
+      cout<<"; aNewPts = {"<<aNewPts[0]<<", "<<aNewPts[1]<<", "<<aNewPts[2]<<"}\n";
+    }
+    
+    if(!anIsObserved){
+      // To get coordinates of the points of the traingle face
+      double aCoord[3][3];
+      aPoints->GetPoint(aNewPts[0],aCoord[0]);
+      aPoints->GetPoint(aNewPts[1],aCoord[1]);
+      aPoints->GetPoint(aNewPts[2],aCoord[2]);
+      
+      /* To calculate plane normal for face (aFace)
+
+
+        ^ aNormal
+        |     
+        |   ^ aVector01
+        | /
+        /_________> aVector02
+       
+      
+      */
+      double aVector01[3] = { aCoord[1][0] - aCoord[0][0],
+                                            aCoord[1][1] - aCoord[0][1],
+                                            aCoord[1][2] - aCoord[0][2] };
       
-      for(int i=0;i<numPts;i++)
-         convex_ids.push_back(convex->GetPointId(i));
+      double aVector02[3] = { aCoord[2][0] - aCoord[0][0],
+                                            aCoord[2][1] - aCoord[0][1],
+                                            aCoord[2][2] - aCoord[0][2] };
       
-      GetCenter(theGrid,convex_ids,convex_center);
-
-      for (vtkIdType faceId=0; faceId < aNbFaces; faceId++){
-       vtkCell *aFace = convex->GetFace(faceId);
-       int numFacePts = aFace->GetNumberOfPoints();
-       TCell aIds;
-       
-  int i = 0;
-       for(i=0;i<numFacePts;i++)
-         aIds.push_back(aFace->GetPointId(i));
-
-       float v_a[3],v_b[3],v_convex2face[3]; // vectors
-       float *id_0,*id_1,*id_n;
-       /*=============================================
-                       ,+- - - -  _
-                  _   / id_n   |  v_b {id_0,id_n}
-                 v_b /            _
-                    /          |  v_a {id_0,id_1}
-                   /          
-                  /            |
-                 + id_0
-                  \
-                 _ \           |
-                v_a \
-                     \ id_1    |
-                      "+- - - -
-
-        ============================================*/ 
-       id_0 = theGrid->GetPoint(aIds[0]);
-       id_1 = theGrid->GetPoint(aIds[1]);
-       id_n = theGrid->GetPoint(aIds[numFacePts-1]);
-
-       for(i=0;i<3;i++){
-         v_a[i] = id_1[i] - id_0[i];
-         v_b[i] = id_n[i] - id_0[i];
-         v_convex2face[i] = id_0[i] - convex_center[i];
-       }
-
-       if (vtkMath::Determinant3x3(v_a,v_b,v_convex2face) < 0){
-         ReverseIds(aIds);
-       }
-
-       for(i=0;i<(int)aIds.size();i++){
-         TUIDS &acell = p2faces[aIds[i]];
-         acell.insert(faceId);
-       }
-       
-       f2points[faceId] = aIds;
+      vtkMath::Normalize(aVector01);
+      vtkMath::Normalize(aVector02);
 
-      }
+      // To calculate the normal for the triangle
+      double aNormal[3];
+      vtkMath::Cross(aVector02,aVector01,aNormal);
       
-      TPTOIDS face2face;
-      GetFriends(p2faces,f2points,face2face);
+      vtkMath::Normalize(aNormal);
       
-      TPTOIDS face2points;
+      // To calculate what points belong to the plane
+      // To calculate bounds of the point set
+      double aCenter[3] = {0.0, 0.0, 0.0};
+      {
+        TPointIds::const_iterator anIter = anInitialPointIds.begin();
+        TPointIds::const_iterator anEndIter = anInitialPointIds.end();
+        for(; anIter != anEndIter; anIter++){
+          double aPntCoord[3];
+          vtkIdType aPntId = *anIter;
+          aPoints->GetPoint(aPntId,aPntCoord);
+          
+          double aVector0Pnt[3] = { aPntCoord[0] - aCoord[0][0],
+                                                  aPntCoord[1] - aCoord[0][1],
+                                                  aPntCoord[2] - aCoord[0][2] };
+
+          
+          vtkMath::Normalize(aVector0Pnt);
+          
+          double aNormalPnt[3];
+          // calculate aNormalPnt
+          {
+            double aCosPnt01 = vtkMath::Dot(aVector0Pnt,aVector01);
+            double aCosPnt02 = vtkMath::Dot(aVector0Pnt,aVector02);
+            if(aCosPnt01<-1)
+              aCosPnt01 = -1;
+            if(aCosPnt01>1)
+              aCosPnt01 = 1;
+            if(aCosPnt02<-1)
+              aCosPnt02 = -1;
+            if(aCosPnt02>1)
+              aCosPnt02 = 1;
+
+            double aDist01,aDist02;// deflection from Pi/3 angle (equilateral triangle)
+            double aAngPnt01 = fabs(acos(aCosPnt01));
+            double aAngPnt02 = fabs(acos(aCosPnt02));
+
+            /*  check that triangle similar to equilateral triangle
+                AOC or COB ?
+                aVector0Pnt = (OC)
+                aVector01   = (OB)
+                aVector02   = (OA)
+            
+            B
+            ^ aVector01  C     
+            |           ^ aVector0Pnt  
+            |     _____/ 
+            | ___/
+            |/________> aVector02
+            O          A
+            */
+            aDist01 = fabs(aAngPnt01-(vtkMath::Pi())/3.0); 
+            aDist02 = fabs(aAngPnt02-(vtkMath::Pi())/3.0);
+            
+            // caculate a normal for best triangle
+            if(aDist01 <= aDist02)
+              vtkMath::Cross(aVector0Pnt,aVector01,aNormalPnt);
+            else
+              vtkMath::Cross(aVector0Pnt,aVector02,aNormalPnt);
+
+          }
+          
+          vtkMath::Normalize(aNormalPnt);
+          
+          if(DEBUG_TRIA_EXECUTE)
+            cout<<"\t\taPntId = "<<aPntId<<" {"<<aPntCoord[0]<<", "<<aPntCoord[1]<<", "<<aPntCoord[2]<<"};";
+          
+          double aDist = vtkPlane::DistanceToPlane(aPntCoord,aNormal,aCoord[0]);
+          if(DEBUG_TRIA_EXECUTE) cout<<": aDist = "<<aDist;
+          if(fabs(aDist) < aDistEps){
+            aPointIds.insert(aPntId);
+            aCenter[0] += aPntCoord[0];
+            aCenter[1] += aPntCoord[1];
+            aCenter[2] += aPntCoord[2];
+            if(DEBUG_TRIA_EXECUTE) cout  << "; Added = TRUE" << endl;
+          } else {
+            if(DEBUG_TRIA_EXECUTE) cout  << "; Added = FALSE" << endl;
+          }
+        }
+        size_t aNbPoints = aPointIds.size();
+        aCenter[0] /= aNbPoints;
+        aCenter[1] /= aNbPoints;
+        aCenter[2] /= aNbPoints;
+      }
       
-      // copy TCellArray::f2points to TPTOIDS::face2points
-      for(TCellArray::iterator f2points_iter=f2points.begin();
-         f2points_iter!=f2points.end();
-         f2points_iter++){
-       
-       TUIDS tmp;
-       for(TCell::iterator points_iter=(f2points_iter->second).begin();
-           points_iter!=(f2points_iter->second).end();
-           points_iter++)
-         tmp.insert(*points_iter);
-       
-       face2points[f2points_iter->first] = tmp;
-      } // end copy
-       
+      //To sinchronize orientation of the cell and its face
+      double aVectorC[3] = { aCenter[0] - aCellCenter[0],
+                                           aCenter[1] - aCellCenter[1],
+                                           aCenter[2] - aCellCenter[2] };
+      vtkMath::Normalize(aVectorC);
       
-      TPTOIDS new_face2faces; // which connected and in one plane
+      double aDot = vtkMath::Dot(aNormal,aVectorC);
+      if(DEBUG_TRIA_EXECUTE) {
+        cout<<"\t\taNormal = {"<<aNormal[0]<<", "<<aNormal[1]<<", "<<aNormal[2]<<"}";
+        cout<<"; aVectorC = {"<<aVectorC[0]<<", "<<aVectorC[1]<<", "<<aVectorC[2]<<"}\n";
+        cout<<"\t\taDot = "<<aDot<<"\n";
+      }
+      if(aDot > 0){
+        aNormal[0] = -aNormal[0];
+        aNormal[1] = -aNormal[1];
+        aNormal[2] = -aNormal[2];
+      }
       
-      TPTOIDS::const_iterator aF2FIter = face2face.begin();
-      for(;aF2FIter!=face2face.end();aF2FIter++){
-       vtkIdType f_key = aF2FIter->first;
-       TUIDS &faces = new_face2faces[f_key];
-       //faces.insert(f_key);
-       TUIDS f_friends = aF2FIter->second;
-       TUIDS::const_iterator a_friends_iter = f_friends.begin();
-       for(;a_friends_iter!=f_friends.end();a_friends_iter++){
-         vtkIdType friend_id = *a_friends_iter;
-         if( IsConnectedFacesOnOnePlane(theGrid,f_key,friend_id,
-                                       (face2points.find(f_key))->second,
-                                       (face2points.find(friend_id))->second)){
-           faces.insert(friend_id);
-         } // end if
-         
-       } // end a_friends_iter
-      } // end aF2FIter
+      // To calculate the primary direction for point set
+      double aVector0[3] = { aCoord[0][0] - aCenter[0],
+                                           aCoord[0][1] - aCenter[1],
+                                           aCoord[0][2] - aCenter[2] };
+      vtkMath::Normalize(aVector0);
       
-      if(MYDEBUG)
-      {
-       TPTOIDS::const_iterator new_face2face_iter = new_face2faces.begin();
-       cout << "Connected faces and on plane:" << endl;
-       for(;new_face2face_iter!=new_face2faces.end();new_face2face_iter++){
-         cout << "Group ["<<new_face2face_iter->first<<"] :";
-         TUIDS::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
-         for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++)
-           cout << " " << *new_faces_iter ;
-         cout << endl;
-       }
+      if(DEBUG_TRIA_EXECUTE) {
+        cout<<"\t\taCenter = {"<<aCenter[0]<<", "<<aCenter[1]<<", "<<aCenter[2]<<"}";
+        cout<<"; aVector0 = {"<<aVector0[0]<<", "<<aVector0[1]<<", "<<aVector0[2]<<"}\n";
       }
       
-      TPTOIDS output_newid2face;
-      TCellArray output_newid2face_v2;
+      // To calculate the set of points by face those that belong to the plane
+      TFace2PointIds aRemoveFace2PointIds;
       {
-       TUIDS already_in;
-       TUIDS already_in_tmp;
-       int k=0;
-       TPTOIDS::const_iterator new_face2face_iter = new_face2faces.begin();
-       for(;new_face2face_iter!=new_face2faces.end();new_face2face_iter++){
-         if(already_in.find(new_face2face_iter->first) != already_in.end())
-           continue;
-         if(new_face2face_iter->second.size() > 1)
-           continue;
-         
-         TCell &tmp_v2 = output_newid2face_v2[k];
-         tmp_v2.push_back(new_face2face_iter->first);
-         already_in.insert(new_face2face_iter->first);
-         
-         TUIDS::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
-         for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++){
-           if(already_in.find(*new_faces_iter) != already_in.end()) continue;
-           already_in.insert(*new_faces_iter);
-           
-           already_in_tmp.clear();
-           already_in_tmp.insert(new_face2face_iter->first);
-
-           TUIDS &tmp = output_newid2face[k];
-           GetAllFacesOnOnePlane(new_face2faces,*new_faces_iter,
-                                 already_in_tmp,tmp_v2);
-           
-           for(TUIDS::const_iterator aIter=already_in_tmp.begin();
-               aIter!=already_in_tmp.end();
-               aIter++)
-             {
-               already_in.insert(*aIter);
-               tmp.insert(*aIter);
-             }
-         }
-         k++;
-       }
+        TFace2PointIds::const_iterator anIter = aFace2PointIds.begin();
+        TFace2PointIds::const_iterator anEndIter = aFace2PointIds.end();
+        for(; anIter != anEndIter; anIter++){
+          const TPointIds& anIds = *anIter;
+          TPointIds anIntersection;
+          std::set_intersection(aPointIds.begin(),aPointIds.end(),
+                                anIds.begin(),anIds.end(),
+                                std::inserter(anIntersection,anIntersection.begin()));
+          
+
+          if(DEBUG_TRIA_EXECUTE) {
+            cout << "anIntersection:";
+            TPointIds::iterator aII = anIntersection.begin();
+            for(;aII!=anIntersection.end();aII++)
+              cout << *aII << ",";
+            cout << endl;
+            cout << "anIds         :";
+            TPointIds::const_iterator aIIds = anIds.begin();
+            for(;aIIds!=anIds.end();aIIds++)
+              cout << *aIIds << ",";
+            cout << endl;
+          }
+          if(anIntersection == anIds){
+            aRemoveFace2PointIds.insert(anIds);
+          }
+        }
       }
       
-      if(MYDEBUG) {
-       cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"<<endl;
-       {
-         TPTOIDS::const_iterator new_face2face_iter = output_newid2face.begin();
-         for(;new_face2face_iter!=output_newid2face.end();new_face2face_iter++){
-           cout << "Group ["<<new_face2face_iter->first<<"] :";
-           TUIDS::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
-           for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++)
-             cout << " " << *new_faces_iter ;
-           cout << endl;
-         }
-       }
-       cout << "++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++"<<endl;
-       cout << "++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++"<<endl;
-       cout << "+++++++++++++++++++++++ ++ ++ ++++++++++++++++++++++++++++"<<endl;
-       cout << "+++++++++++++++++++++++++   ++++++++++++++++++++++++++++++"<<endl;
-       cout << "++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++"<<endl;
-       {
-         TCellArray::const_iterator new_face2face_iter = output_newid2face_v2.begin();
-         for(;new_face2face_iter!=output_newid2face_v2.end();new_face2face_iter++){
-           cout << "Group ["<<new_face2face_iter->first<<"] :";
-           TCell::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
-           for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++)
-             cout << " " << *new_faces_iter ;
-           cout << endl;
-         }
-       }
+      // To remove from the set of points by face those that belong to the plane
+      {
+        TFace2PointIds::const_iterator anIter = aRemoveFace2PointIds.begin();
+        TFace2PointIds::const_iterator anEndIter = aRemoveFace2PointIds.end();
+        for(; anIter != anEndIter; anIter++){
+          const TPointIds& anIds = *anIter;
+          aFace2PointIds.erase(anIds);
+        }
       }
-      TCellArray output_new_face2ids;
-//       {
-//     TPTOIDS::const_iterator new_face2face_iter = output_newid2face.begin();
-//     for(;new_face2face_iter!=output_newid2face.end();new_face2face_iter++){
-         
-//       vtkIdType new_faceId = new_face2face_iter->first;
-//       TUIDS::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
-//       vtkIdType fId0 = *new_faces_iter;
-//       TCellArray::const_iterator pIds0_iter = f2points.find(fId0);
-//       TCell pIds0 = pIds0_iter->second;
-//       TCell &output = output_new_face2ids[new_faceId];
-//       new_faces_iter++;
-//       if(new_face2face_iter->second.size() > 2 ){}
-//       for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++){
-           
-//         vtkIdType faceId = *new_faces_iter;
-//         // find how much nodes in face (f2points)
-//         TCellArray::const_iterator pIds_iter = f2points.find(faceId);
-//         TCell pIds = pIds_iter->second;
-           
-//         GetSumm(pIds0,pIds,output);
-//         pIds0 = output;
-
-//       } // end new_faces_iter
-         
-//     } // new_face2face_iter
-//       }
       
+      // To sort the planar set of the points accrding to the angle
       {
-       TCellArray::const_iterator new_face2face_iter = output_newid2face_v2.begin();
-       for(;new_face2face_iter!=output_newid2face_v2.end();new_face2face_iter++){
-         
-         vtkIdType new_faceId = new_face2face_iter->first;
-         TCell::const_iterator new_faces_iter = (new_face2face_iter->second).begin();
-         vtkIdType fId0 = *new_faces_iter;
-         TCellArray::const_iterator pIds0_iter = f2points.find(fId0);
-         TCell pIds0 = pIds0_iter->second;
-         TCell &output = output_new_face2ids[new_faceId];
-         new_faces_iter++;
-         if(new_face2face_iter->second.size() == 1 ){
-           TCellArray::const_iterator pIds_iter = f2points.find(fId0);
-           TCell pIds = pIds_iter->second;
-           output = pIds;
-           continue;
-         }
-         for(;new_faces_iter!=(new_face2face_iter->second).end();new_faces_iter++){
-           
-           vtkIdType faceId = *new_faces_iter;
-           // find how much nodes in face (f2points)
-           TCellArray::const_iterator pIds_iter = f2points.find(faceId);
-           TCell pIds = pIds_iter->second;
-           
-           GetSumm(pIds0,pIds,output);
-           pIds0 = output;
-
-         } // end new_faces_iter
-         
-       } // new_face2face_iter
+        typedef std::map<double,vtkIdType> TSortedPointIds;
+        TSortedPointIds aSortedPointIds;
+        
+        TPointIds::const_iterator anIter = aPointIds.begin();
+        TPointIds::const_iterator anEndIter = aPointIds.end();
+        for(; anIter != anEndIter; anIter++){
+          double aPntCoord[3];
+          vtkIdType aPntId = *anIter;
+          aPoints->GetPoint(aPntId,aPntCoord);
+          double aVector[3] = { aPntCoord[0] - aCenter[0],
+                                              aPntCoord[1] - aCenter[1],
+                                              aPntCoord[2] - aCenter[2] };
+          vtkMath::Normalize(aVector);
+          
+          double aCross[3];
+          vtkMath::Cross(aVector,aVector0,aCross);
+          double aCr = vtkMath::Dot(aCross,aNormal);
+          bool aGreaterThanPi = aCr < 0;
+          double aCosinus = vtkMath::Dot(aVector,aVector0);
+          double anAngle = 0.0;
+          if(aCosinus >= 1.0){
+            aCosinus = 1.0;
+          } else if (aCosinus <= -1.0){
+            aCosinus = -1.0;
+            anAngle = vtkMath::Pi();
+          } else {
+            anAngle = acos(aCosinus);
+            if(aGreaterThanPi)
+              anAngle = 2*vtkMath::Pi() - anAngle;
+          }
+          
+          if(DEBUG_TRIA_EXECUTE) {
+            cout << "\t\t\t vtkMath::Dot(aCross,aNormal)="<<aCr<<endl;
+            cout<<"\t\t\taPntId = "<<aPntId<<" {"<<aPntCoord[0]<<", "<<aPntCoord[1]<<", "<<aPntCoord[2]<<"}";
+            cout<<"; aGreaterThanPi = "<<aGreaterThanPi<<"; aCosinus = "<<aCosinus<<"; anAngle = "<<anAngle<<"\n";
+          }
+          aSortedPointIds[anAngle] = aPntId;
+        }
+
+        if(!aSortedPointIds.empty()){
+          size_t aNumFacePts = aSortedPointIds.size();
+          ::TConnectivities aConnectivities(aNumFacePts);
+          TSortedPointIds::const_iterator anIter = aSortedPointIds.begin();
+          TSortedPointIds::const_iterator anEndIter = aSortedPointIds.end();
+          if(DEBUG_TRIA_EXECUTE) cout << "Polygon:";
+          for(vtkIdType anId = 0; anIter != anEndIter; anIter++, anId++){
+            vtkIdType aPntId = anIter->second;
+            aConnectivities[anId] = GetConnectivity(aPntId);
+            if(DEBUG_TRIA_EXECUTE) cout << aPntId << ",";
+          }
+          if(DEBUG_TRIA_EXECUTE) cout << endl;
+          aPolygons.push_back(::TPolygon(aConnectivities,aCenter,aNormal));
+        }
       }
-      
-      if(MYDEBUG) {
-       cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"<<endl;
-       cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"<<endl;
-       cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"<<endl;
+    }
+  }
+  if(aPolygons.empty())
+    return true;
+
+  // To check, whether the polygons give a convex polyhedron or not
+  if(theIsCheckConvex){
+    size_t aNbPolygons = aPolygons.size();
+    for (size_t aPolygonId = 0; aPolygonId < aNbPolygons; aPolygonId++) {
+      ::TPolygon& aPolygon = aPolygons[aPolygonId];
+      double* aNormal = aPolygon.myNormal;
+      double* anOrigin = aPolygon.myOrigin;
+      if(DEBUG_TRIA_EXECUTE) {
+        cout<<"\taPolygonId = "<<aPolygonId<<"\n";
+        cout<<"\t\taNormal = {"<<aNormal[0]<<", "<<aNormal[1]<<", "<<aNormal[2]<<"}";
+        cout<<"; anOrigin = {"<<anOrigin[0]<<", "<<anOrigin[1]<<", "<<anOrigin[2]<<"}\n";
       }
-      outputCellArray = output_new_face2ids;//f2points;
+      for(vtkIdType aPntId = 0; aPntId < aNumPts; aPntId++){
+        double aPntCoord[3];
+        vtkIdType anId = GetPointId(aPntId);
+        aPoints->GetPoint(anId,aPntCoord);
+        double aDist = vtkPlane::Evaluate(aNormal,anOrigin,aPntCoord);
+        if(DEBUG_TRIA_EXECUTE) cout<<"\t\taPntId = "<<anId<<" {"<<aPntCoord[0]<<", "<<aPntCoord[1]<<", "<<aPntCoord[2]<<"}; aDist = "<<aDist<<"\n";
+        if(aDist < -aDistEps)
+          return false;
+      }
+    }
+  }
+
+
+  // To pass resulting set of the polygons to the output
+  {
+    size_t aNbPolygons = aPolygons.size();
+    for (size_t aPolygonId = 0; aPolygonId < aNbPolygons; aPolygonId++) {
+      ::TPolygon& aPolygon = aPolygons[aPolygonId];
+      if(DEBUG_TRIA_EXECUTE) cout << "PoilygonId="<<aPolygonId<<" | ";
+      TConnectivities& aConnectivities = aPolygon.myConnectivities;
+      if(DEBUG_TRIA_EXECUTE) {
+        for(size_t i=0;i<aConnectivities.size();i++)
+          cout << aConnectivities[i] << ",";
+        cout << endl;
+      }
+      int aNbPoints = (int)aConnectivities.size();
+      vtkIdType aNewCellId = theOutput->InsertNextCell(VTK_POLYGON,aNbPoints,&aConnectivities[0]);
+      if(theStoreMapping)
+        VTKViewer_GeometryFilter::InsertId( theCellId, VTK_POLYGON, theVTK2ObjIds, theDimension2VTK2ObjIds );
+      theOutputCD->CopyData(thInputCD,theCellId,aNewCellId);
+    }
+  }
+
+  if(DEBUG_TRIA_EXECUTE) cout<<"\tTriangulator - Ok\n";
+  
+  return true;
+}
+
+
+//----------------------------------------------------------------------------
+VTKViewer_OrderedTriangulator
+::VTKViewer_OrderedTriangulator():
+  myTriangulator(vtkOrderedTriangulator::New()),
+  myBoundaryTris(vtkCellArray::New()),
+  myTriangle(vtkTriangle::New())
+{
+  myBoundaryTris->Allocate(VTK_CELL_SIZE);
+  myTriangulator->PreSortedOff();
+}
+
+
+//----------------------------------------------------------------------------
+VTKViewer_OrderedTriangulator
+::~VTKViewer_OrderedTriangulator()
+{
+  myTriangle->Delete();
+  myBoundaryTris->Delete();
+  myTriangulator->Delete();
+}
+
+
+//----------------------------------------------------------------------------
+vtkPoints*
+VTKViewer_OrderedTriangulator
+::InitPoints(vtkUnstructuredGrid *theInput,
+             vtkIdType theCellId)
+{
+  myBoundaryTris->Reset();
+
+  vtkPoints* aPoints = VTKViewer_Triangulator::InitPoints(theInput, theCellId);
+  vtkIdType aNumPts = myPoints->GetNumberOfPoints();
+  if ( aNumPts > 0 ) {
+    myTriangulator->InitTriangulation(0.0, 1.0, 0.0, 1.0, 0.0, 1.0, aNumPts);
+
+    double aBounds[6];
+    myPoints->GetBounds(aBounds);
+    double xSize, ySize, zSize;
+    xSize = aBounds[1] - aBounds[0];
+    ySize = aBounds[3] - aBounds[2];
+    zSize = aBounds[5] - aBounds[4];
+    double anAbsoluteCoord[3];
+    double aParamentrucCoord[3];
+    for (auto aPntId = 0; aPntId < aNumPts; aPntId++) {
+      myPoints->GetPoint(aPntId, anAbsoluteCoord);
+      aParamentrucCoord[0] = xSize==0. ? 0. : ((anAbsoluteCoord[0] - aBounds[0]) / xSize);
+      aParamentrucCoord[1] = ySize==0. ? 0. : ((anAbsoluteCoord[1] - aBounds[2]) / ySize);
+      aParamentrucCoord[2] = zSize==0. ? 0. : ((anAbsoluteCoord[2] - aBounds[4]) / zSize);
+      myTriangulator->InsertPoint(aPntId, anAbsoluteCoord, aParamentrucCoord, 0);
     }
-  } else {
-    // not implemented
+
+    myTriangulator->Triangulate();
+    myTriangulator->AddTriangles(myBoundaryTris);
   }
+
+  return aPoints;
+}
+
+
+//----------------------------------------------------------------------------
+vtkIdType 
+VTKViewer_OrderedTriangulator
+::GetNumFaces()
+{
+  return myBoundaryTris->GetNumberOfCells();
+}
+
+
+//----------------------------------------------------------------------------
+vtkCell*
+VTKViewer_OrderedTriangulator
+::GetFace(vtkIdType theFaceId)
+{
+  vtkIdType aNumCells = myBoundaryTris->GetNumberOfCells();
+  if ( theFaceId < 0 || theFaceId >= aNumCells ) 
+    return NULL;
+
+  vtkIdType *aCells = myBoundaryTris->GetData()->GetPointer(0);
+
+  // Each triangle has three points plus number of points
+  vtkIdType *aCellPtr = aCells + 4*theFaceId;
+  
+  myTriangle->PointIds->SetId(0, aCellPtr[1]);
+  myTriangle->Points->SetPoint(0, myPoints->GetPoint(aCellPtr[1]));
+
+  myTriangle->PointIds->SetId(1, aCellPtr[2]);
+  myTriangle->Points->SetPoint(1, myPoints->GetPoint(aCellPtr[2]));
+
+  myTriangle->PointIds->SetId(2, aCellPtr[3]);
+  myTriangle->Points->SetPoint(2, myPoints->GetPoint(aCellPtr[3]));
+
+  return myTriangle;
 }
+
+
+//----------------------------------------------------------------------------
+VTKViewer_DelaunayTriangulator
+::VTKViewer_DelaunayTriangulator():
+  myUnstructuredGrid(vtkUnstructuredGrid::New()),
+  myGeometryFilter(vtkGeometryFilter::New()),
+  myDelaunay3D(vtkDelaunay3D::New()),
+  myPolyData(NULL)
+{
+  myUnstructuredGrid->Initialize();
+  myUnstructuredGrid->Allocate();
+  myUnstructuredGrid->SetPoints(myPoints);
+
+  myDelaunay3D->SetInputData(myUnstructuredGrid);
+  myGeometryFilter->SetInputConnection(myDelaunay3D->GetOutputPort());
+  myPolyData = myGeometryFilter->GetOutput();
+}
+
+
+//----------------------------------------------------------------------------
+VTKViewer_DelaunayTriangulator
+::~VTKViewer_DelaunayTriangulator()
+{
+  myUnstructuredGrid->Delete();
+  myGeometryFilter->Delete();
+  myDelaunay3D->Delete();
+}
+
+
+//----------------------------------------------------------------------------
+vtkPoints* 
+VTKViewer_DelaunayTriangulator
+::InitPoints(vtkUnstructuredGrid *theInput,
+             vtkIdType theCellId)
+{
+  vtkPoints* aPoints = VTKViewer_Triangulator::InitPoints(theInput, theCellId);
+
+  myPoints->Modified();
+  myUnstructuredGrid->Modified();
+  myGeometryFilter->Update();
+  
+  return aPoints;
+}
+
+
+//----------------------------------------------------------------------------
+vtkIdType 
+VTKViewer_DelaunayTriangulator
+::GetNumFaces()
+{
+  return myPolyData->GetNumberOfCells();
+}
+
+
+//----------------------------------------------------------------------------
+vtkCell*
+VTKViewer_DelaunayTriangulator
+::GetFace(vtkIdType theFaceId)
+{
+  return myPolyData->GetCell(theFaceId);
 }