]> SALOME platform Git repositories - modules/visu.git/blob - src/OBJECT/VISU_SelectVisiblePoints.cxx
Salome HOME
1f91cae1210499007f5de3a3fd64a382aaf1a015
[modules/visu.git] / src / OBJECT / VISU_SelectVisiblePoints.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  VISU OBJECT : interactive object for VISU entities implementation
23 //  File   : VISU_SelectVisiblePoints.h
24 //  Author : Oleg UVAROV
25 //  Module : VISU
26
27 #include "VISU_SelectVisiblePoints.h"
28
29 #include "vtkCamera.h"
30 #include "vtkCellArray.h"
31 #include "vtkDataSet.h"
32 #include "vtkMatrix4x4.h"
33 #include "vtkInformation.h"
34 #include "vtkInformationVector.h"
35 #include "vtkObjectFactory.h"
36 #include "vtkPointData.h"
37 #include "vtkPoints.h"
38 #include "vtkPolyData.h"
39 #include "vtkRenderWindow.h"
40 #include "vtkRenderer.h"
41
42 vtkStandardNewMacro(VISU_SelectVisiblePoints);
43
44 // Instantiate object with no renderer; window selection turned off; 
45 // tolerance set to 0.01; and select invisible off.
46 VISU_SelectVisiblePoints::VISU_SelectVisiblePoints()
47 {
48   this->Offset[0] = this->Offset[1] = this->Offset[2] = 0.0;
49 }
50
51 VISU_SelectVisiblePoints::~VISU_SelectVisiblePoints()
52 {
53 }
54
55 int VISU_SelectVisiblePoints::RequestData(
56   vtkInformation *vtkNotUsed(request),
57   vtkInformationVector **inputVector,
58   vtkInformationVector *outputVector)
59 {
60   // get the info objects
61   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
62   vtkInformation *outInfo = outputVector->GetInformationObject(0);
63
64   // get the input and ouptut
65   vtkDataSet *input = vtkDataSet::SafeDownCast(
66     inInfo->Get(vtkDataObject::DATA_OBJECT()));
67   vtkPolyData *output = vtkPolyData::SafeDownCast(
68     outInfo->Get(vtkDataObject::DATA_OBJECT()));
69
70   vtkIdType ptId, cellId;
71   int visible;
72   vtkPoints *outPts;
73   vtkCellArray *outputVertices;
74   vtkPointData *inPD=input->GetPointData();
75   vtkPointData *outPD=output->GetPointData();
76   vtkIdType numPts=input->GetNumberOfPoints();
77   double x[4], xTrans[4];
78   double dx[3], z;
79   int selection[4];
80   
81   if ( this->Renderer == NULL )
82     {
83     vtkErrorMacro(<<"Renderer must be set");
84     return 0;
85     }
86
87   if ( numPts < 1 )
88     {
89     return 0;
90     }
91   
92   outPts = vtkPoints::New();
93   outPts->Allocate(numPts/2+1);
94   outPD->CopyAllocate(inPD);
95
96   outputVertices = vtkCellArray::New();
97   output->SetVerts(outputVertices);
98   outputVertices->Delete();
99
100   int *size = this->Renderer->GetRenderWindow()->GetSize();
101
102   // specify a selection window to avoid querying 
103   if ( this->SelectionWindow )
104     {
105     for (int i=0; i<4; i++)
106       {
107       selection[i] = this->Selection[i];
108       }
109     }
110   else
111     {
112     selection[0] = selection[2] = 0;
113     selection[1] = size[0] - 1;
114     selection[3] = size[1] - 1;
115     }
116
117   // Grab the composite perspective transform.  This matrix is used to convert
118   // each point to view coordinates.  vtkRenderer provides a WorldToView()
119   // method but it computes the composite perspective transform each time
120   // WorldToView() is called.  This is expensive, so we get the matrix once
121   // and handle the transformation ourselves.
122   vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
123   double view[4];
124   matrix->DeepCopy(this->Renderer->GetActiveCamera()->
125                    GetCompositePerspectiveTransformMatrix(
126                      this->Renderer->GetTiledAspectRatio(),0,1));
127
128   // If we have more than a few query points, we grab the z-buffer for the
129   // selection region all at once and probe the resulting array.  When we
130   // have just a few points, we perform individual z-buffer queries.
131   const int SimpleQueryLimit = 25;
132   float *zPtr = NULL;
133   if (numPts > SimpleQueryLimit)
134     {
135     zPtr = this->Renderer->GetRenderWindow()->
136       GetZbufferData(selection[0], selection[2], selection[1], selection[3]);
137     }
138   
139   int abort=0;
140   vtkIdType progressInterval=numPts/20+1;
141   x[3] = 1.0;
142   for (cellId=(-1), ptId=0; ptId < numPts && !abort; ptId++)
143     {
144     // perform conversion
145     input->GetPoint(ptId,x);
146
147     // take into account translation offset (this is the only difference
148     // between this class and native vtkSelectVisiblePoints class)
149     xTrans[0] = x[0] + this->Offset[0];
150     xTrans[1] = x[1] + this->Offset[1];
151     xTrans[2] = x[2] + this->Offset[2];
152     xTrans[3] = 1.0;
153
154     matrix->MultiplyPoint(xTrans, view);
155     if (view[3] == 0.0)
156       {
157       continue;
158       }
159     this->Renderer->SetViewPoint(view[0]/view[3], view[1]/view[3],
160                                  view[2]/view[3]);
161     this->Renderer->ViewToDisplay();
162     this->Renderer->GetDisplayPoint(dx);
163     visible = 0;
164
165     if ( ! (ptId % progressInterval) ) 
166       {
167       this->UpdateProgress((double)ptId/numPts);
168       abort = this->GetAbortExecute();
169       }
170
171     // check whether visible and in selection window 
172     if ( dx[0] >= selection[0] && dx[0] <= selection[1] &&
173          dx[1] >= selection[2] && dx[1] <= selection[3] )
174       {
175       if (numPts > SimpleQueryLimit)
176         {
177         // Access the value from the captured zbuffer.  Note, we only
178         // captured a portion of the zbuffer, so we need to offset dx by
179         // the selection window.
180         z = zPtr[(int)dx[0] - selection[0]
181                  + ((int)dx[1] - selection[2])
182                  *(selection[1] - selection[0] + 1)];
183         }
184       else
185         {
186         z = this->Renderer->GetZ(static_cast<int>(dx[0]), 
187                                  static_cast<int>(dx[1]));
188         }
189       if( dx[2] < (z + this->Tolerance) ) 
190         {
191         visible = 1;
192         }
193       }
194
195     if ( (visible && !this->SelectInvisible) ||
196          (!visible && this->SelectInvisible) )
197       {
198       cellId = outPts->InsertNextPoint(x);
199       output->InsertNextCell(VTK_VERTEX, 1, &cellId);
200       outPD->CopyData(inPD,ptId,cellId);
201       }
202     }//for all points
203
204   output->SetPoints(outPts);
205   outPts->Delete();
206   output->Squeeze();
207
208   matrix->Delete();
209
210   if (zPtr)
211     {
212     delete [] zPtr;
213     }
214
215   vtkDebugMacro(<<"Selected " << cellId + 1 << " out of " 
216                 << numPts << " original points");
217
218   return 1;
219 }
220
221 void VISU_SelectVisiblePoints::PrintSelf(ostream& os, vtkIndent indent)
222 {
223   this->Superclass::PrintSelf(os,indent);
224
225   os << indent << "Offset: ("
226      << this->Offset[0] << ", "
227      << this->Offset[1] << ", "
228      << this->Offset[2] << ")\n";
229 }