1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // VISU OBJECT : interactive object for VISU entities implementation
21 // File : VISU_SelectVisiblePoints.h
22 // Author : Oleg UVAROV
25 #include "VISU_SelectVisiblePoints.h"
27 #include "vtkCamera.h"
28 #include "vtkCellArray.h"
29 #include "vtkDataSet.h"
30 #include "vtkMatrix4x4.h"
31 #include "vtkInformation.h"
32 #include "vtkInformationVector.h"
33 #include "vtkObjectFactory.h"
34 #include "vtkPointData.h"
35 #include "vtkPoints.h"
36 #include "vtkPolyData.h"
37 #include "vtkRenderWindow.h"
38 #include "vtkRenderer.h"
40 vtkStandardNewMacro(VISU_SelectVisiblePoints);
42 // Instantiate object with no renderer; window selection turned off;
43 // tolerance set to 0.01; and select invisible off.
44 VISU_SelectVisiblePoints::VISU_SelectVisiblePoints()
46 this->Offset[0] = this->Offset[1] = this->Offset[2] = 0.0;
49 VISU_SelectVisiblePoints::~VISU_SelectVisiblePoints()
53 int VISU_SelectVisiblePoints::RequestData(
54 vtkInformation *vtkNotUsed(request),
55 vtkInformationVector **inputVector,
56 vtkInformationVector *outputVector)
58 // get the info objects
59 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
60 vtkInformation *outInfo = outputVector->GetInformationObject(0);
62 // get the input and ouptut
63 vtkDataSet *input = vtkDataSet::SafeDownCast(
64 inInfo->Get(vtkDataObject::DATA_OBJECT()));
65 vtkPolyData *output = vtkPolyData::SafeDownCast(
66 outInfo->Get(vtkDataObject::DATA_OBJECT()));
68 vtkIdType ptId, cellId;
71 vtkCellArray *outputVertices;
72 vtkPointData *inPD=input->GetPointData();
73 vtkPointData *outPD=output->GetPointData();
74 vtkIdType numPts=input->GetNumberOfPoints();
75 double x[4], xTrans[4];
79 if ( this->Renderer == NULL )
81 vtkErrorMacro(<<"Renderer must be set");
90 outPts = vtkPoints::New();
91 outPts->Allocate(numPts/2+1);
92 outPD->CopyAllocate(inPD);
94 outputVertices = vtkCellArray::New();
95 output->SetVerts(outputVertices);
96 outputVertices->Delete();
98 int *size = this->Renderer->GetRenderWindow()->GetSize();
100 // specify a selection window to avoid querying
101 if ( this->SelectionWindow )
103 for (int i=0; i<4; i++)
105 selection[i] = this->Selection[i];
110 selection[0] = selection[2] = 0;
111 selection[1] = size[0] - 1;
112 selection[3] = size[1] - 1;
115 // Grab the composite perspective transform. This matrix is used to convert
116 // each point to view coordinates. vtkRenderer provides a WorldToView()
117 // method but it computes the composite perspective transform each time
118 // WorldToView() is called. This is expensive, so we get the matrix once
119 // and handle the transformation ourselves.
120 vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
122 matrix->DeepCopy(this->Renderer->GetActiveCamera()->
123 GetCompositeProjectionTransformMatrix(this->Renderer->GetTiledAspectRatio(),0,1));
125 // If we have more than a few query points, we grab the z-buffer for the
126 // selection region all at once and probe the resulting array. When we
127 // have just a few points, we perform individual z-buffer queries.
128 const int SimpleQueryLimit = 25;
130 if (numPts > SimpleQueryLimit)
132 zPtr = this->Renderer->GetRenderWindow()->
133 GetZbufferData(selection[0], selection[2], selection[1], selection[3]);
137 vtkIdType progressInterval=numPts/20+1;
139 for (cellId=(-1), ptId=0; ptId < numPts && !abort; ptId++)
141 // perform conversion
142 input->GetPoint(ptId,x);
144 // take into account translation offset (this is the only difference
145 // between this class and native vtkSelectVisiblePoints class)
146 xTrans[0] = x[0] + this->Offset[0];
147 xTrans[1] = x[1] + this->Offset[1];
148 xTrans[2] = x[2] + this->Offset[2];
151 matrix->MultiplyPoint(xTrans, view);
156 this->Renderer->SetViewPoint(view[0]/view[3], view[1]/view[3],
158 this->Renderer->ViewToDisplay();
159 this->Renderer->GetDisplayPoint(dx);
162 if ( ! (ptId % progressInterval) )
164 this->UpdateProgress((double)ptId/numPts);
165 abort = this->GetAbortExecute();
168 // check whether visible and in selection window
169 if ( dx[0] >= selection[0] && dx[0] <= selection[1] &&
170 dx[1] >= selection[2] && dx[1] <= selection[3] )
172 if (numPts > SimpleQueryLimit)
174 // Access the value from the captured zbuffer. Note, we only
175 // captured a portion of the zbuffer, so we need to offset dx by
176 // the selection window.
177 z = zPtr[(int)dx[0] - selection[0]
178 + ((int)dx[1] - selection[2])
179 *(selection[1] - selection[0] + 1)];
183 z = this->Renderer->GetZ(static_cast<int>(dx[0]),
184 static_cast<int>(dx[1]));
186 if( dx[2] < (z + this->Tolerance) )
192 if ( (visible && !this->SelectInvisible) ||
193 (!visible && this->SelectInvisible) )
195 cellId = outPts->InsertNextPoint(x);
196 output->InsertNextCell(VTK_VERTEX, 1, &cellId);
197 outPD->CopyData(inPD,ptId,cellId);
201 output->SetPoints(outPts);
212 vtkDebugMacro(<<"Selected " << cellId + 1 << " out of "
213 << numPts << " original points");
218 void VISU_SelectVisiblePoints::PrintSelf(ostream& os, vtkIndent indent)
220 this->Superclass::PrintSelf(os,indent);
222 os << indent << "Offset: ("
223 << this->Offset[0] << ", "
224 << this->Offset[1] << ", "
225 << this->Offset[2] << ")\n";