0025991: Cyclic dependency in OCCT detected by WOK compiler
[occt.git] / src / IVtkOCC / IVtkOCC_ViewerSelector.cxx
CommitLineData
913a4c4a 1// Created on: 2011-10-20
2// Created by: Roman KOZLOV
3// Copyright (c) 2011-2014 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#include <IVtkOCC_ViewerSelector.hxx>
17#include <Select3D_SensitiveBox.hxx>
18#include <TColgp_Array1OfPnt2d.hxx>
19#include <gp_Quaternion.hxx>
20#include <Graphic3d_Camera.hxx>
21
22IMPLEMENT_STANDARD_HANDLE( IVtkOCC_ViewerSelector, SelectMgr_ViewerSelector )
23IMPLEMENT_STANDARD_RTTIEXT( IVtkOCC_ViewerSelector, SelectMgr_ViewerSelector )
24
25//============================================================================
26// Method: Constructor
27// Purpose:
28//============================================================================
29IVtkOCC_ViewerSelector::IVtkOCC_ViewerSelector()
30: SelectMgr_ViewerSelector(),
31myPixTol(2),
32myToUpdateTol(Standard_True)
33{
34 for (Standard_Integer i=0;i<=13;i++) {myCoeff [i] = 0.;myPrevCoeff[i]=0.0;}
35 for (Standard_Integer j=0;j<2;j++) {myCenter [j] = 0.;myPrevCenter[j]=0.0;}
36}
37
38//============================================================================
39// Method: Convert
40// Purpose: Projects all sensitive entities from the given selection container
41// to 2D space
42//============================================================================
43void IVtkOCC_ViewerSelector::Convert (const Handle(SelectMgr_Selection)& theSelection)
44{
45 for (theSelection->Init(); theSelection->More(); theSelection->Next())
46 {
47 if(theSelection->Sensitive()->NeedsConversion())
48 {
49 Handle(Select3D_SensitiveEntity) aSensEntity =
50 *((Handle(Select3D_SensitiveEntity)*) &(theSelection->Sensitive()));
51 aSensEntity->Project (myPrj);
52 if (!tosort)
53 {
54 tosort = Standard_True;
55 }
56 }
57 }
58}
59
60//============================================================================
61// Method: Pick
62// Purpose: Implements point picking
63//============================================================================
64void IVtkOCC_ViewerSelector::Pick (const Standard_Integer theXPix,
65 const Standard_Integer theYPix,
66 const IVtk_IView::Handle& theView)
67{
68 myclip.SetVoid();
69 Update (theView);
70 gp_XY aDispPnt (theXPix, theYPix);
71 gp_XYZ aWorldPnt;
72 gp_Pnt2d aP2d;
73 theView->DisplayToWorld (aDispPnt, aWorldPnt);
74 myPrj->Project (gp_Pnt (aWorldPnt), aP2d);
75 InitSelect (aP2d.X(), aP2d.Y());
76}
77
78//============================================================================
79// Method: Pick
80// Purpose: Picking by rectangle
81//============================================================================
82void IVtkOCC_ViewerSelector::Pick (const Standard_Integer theXMin,
83 const Standard_Integer theYMin,
84 const Standard_Integer theXMax,
85 const Standard_Integer theYMax,
86 const IVtk_IView::Handle& theView)
87{
88 if (myToUpdateTol)
89 {
90 // Compute and set a sensitivity tolerance according to the renderer (viewport).
91 // TODO: Think if this works well in perspective view...'cause result depends
92 // on position on the screen, but we always use the point close to the
93 // screen's origin...
94 gp_XYZ aWorldPnt1, aWorldPnt2;
95 gp_XY aDispPnt1 (0.0, 0.0);
96 gp_XY aDispPnt2 (myPixTol, 0.0);
97 theView->DisplayToWorld (aDispPnt1, aWorldPnt1);
98 theView->DisplayToWorld (aDispPnt2, aWorldPnt2);
99 gp_Pnt aPnt1 (aWorldPnt1);
100 gp_Pnt aPnt2 (aWorldPnt2);
101 SetSensitivity (aPnt2.Distance (aPnt1));
102 myToUpdateTol = Standard_False;
103 }
104 Update (theView);
105
106 gp_XY aDispPnt1 (theXMin, theYMin);
107 gp_XY aDispPnt2 (theXMax, theYMax);
108 gp_XYZ aWorldPnt1, aWorldPnt2;
109
110 gp_Pnt2d aP2d_1, aP2d_2;
111 theView->DisplayToWorld (aDispPnt1, aWorldPnt1);
112 theView->DisplayToWorld (aDispPnt2, aWorldPnt2);
113
114 myPrj->Project (gp_Pnt (aWorldPnt1), aP2d_1);
115 myPrj->Project (gp_Pnt (aWorldPnt2), aP2d_2);
116
117 InitSelect (Min (aP2d_1.X(), aP2d_2.X()),
118 Min (aP2d_1.Y(), aP2d_2.Y()),
119 Max (aP2d_1.X(), aP2d_2.X()),
120 Max (aP2d_1.Y(), aP2d_2.Y()));
121}
122
123//============================================================================
124// Method: Pick
125// Purpose:
126//============================================================================
127void IVtkOCC_ViewerSelector::Pick (double** thePoly,
128 const int theNbPoints,
129 const IVtk_IView::Handle& theView)
130{
131 TColgp_Array1OfPnt2d aPolyline (1, theNbPoints);
132
133 if (myToUpdateTol)
134 {
135 // Compute and set a sensitivity tolerance according to the renderer (viewport).
136 // TODO: Think if this works well in perspective view...'cause result depends
137 // on position on the screen, but we always use the point close to the
138 // screen's origin...
139 gp_XYZ aWorldPnt1, aWorldPnt2;
140 gp_XY aDispPnt1 (0.0, 0.0);
141 gp_XY aDispPnt2 (myPixTol, 0.0);
142 theView->DisplayToWorld (aDispPnt1, aWorldPnt1);
143 theView->DisplayToWorld (aDispPnt2, aWorldPnt2);
144 gp_Pnt aPnt1 (aWorldPnt1);
145 gp_Pnt aPnt2 (aWorldPnt2);
146 SetSensitivity (aPnt2.Distance (aPnt1));
147 myToUpdateTol = Standard_False;
148 }
149
150 Update (theView);
151
152 // Build TColgp_Array1OfPnt2d from input array of doubles
153 gp_XYZ aWorldPnt;
154
155 for (Standard_Integer anIt = 0; anIt < theNbPoints; anIt++)
156 {
157 gp_XY aDispPnt = thePoly[anIt][2] != 0 ? gp_XY (thePoly[anIt][0] / thePoly[anIt][2], thePoly[anIt][1] / thePoly[anIt][2])
158 : gp_XY (thePoly[anIt][0], thePoly[anIt][1]);
159 gp_Pnt2d aP2d;
160 theView->DisplayToWorld (aDispPnt, aWorldPnt);
161 myPrj->Project (gp_Pnt (aWorldPnt), aP2d);
162 aPolyline.SetValue (anIt + 1, aP2d);
163 }
164
165 InitSelect (aPolyline);
166}
167
168//============================================================================
169// Method: Update
170// Purpose: Checks if some projection parameters have changed,
171// and updates the 2D projections of all sensitive entities if necessary.
172//============================================================================
173Standard_Boolean IVtkOCC_ViewerSelector::Update (const IVtk_IView::Handle& theView)
174{
175 static Standard_Real aZoom (0.0);
176
177 // No focal distance by default
178 myPrevCoeff[9] = 0.0;
179 // Parallel projection by default
180 myPrevCoeff[10] = 0.0;
181
182 // Flag related to perspective or parallel projection
183 Standard_Boolean isPerspective = theView->IsPerspective();
184
185 // For perspective projections only
186 if (isPerspective)
187 {
188 // Flag = 1 if perspective projection
189 myPrevCoeff[10] = 1.0;
190 // Focal distance
191 myPrevCoeff[9] = theView->GetDistance();
192 }
193 // View point
194 // Use (0,0,0) as a view reference point:
195
196 theView->GetPosition (myPrevCoeff[0], myPrevCoeff[1], myPrevCoeff[2]);
197
198 // Orientation
199 theView->GetViewUp (myPrevCoeff[3], myPrevCoeff[4], myPrevCoeff[5]);
200 // Projection direction vector
201 theView->GetDirectionOfProjection (myPrevCoeff[6], myPrevCoeff[7], myPrevCoeff[8]);
202
203 // 3D Scale
204 theView->GetScale (myPrevCoeff[11], myPrevCoeff[12], myPrevCoeff[13]);
205
206 // Return the center of this viewport in display coordinates.
207 theView->GetViewCenter (myPrevCenter[0], myPrevCenter[1]);
208
209 Standard_Integer anIt;
210
211 for (anIt=0; anIt <= 13 && (myPrevCoeff[anIt] == myCoeff[anIt]); anIt++) { }
212
213 if (anIt <= 13 || (myPrevCenter[0] != myCenter[0]) || (myPrevCenter[1] != myCenter[1]))
214 {
215 toupdate = Standard_True;
216 myToUpdateTol = Standard_True;
217
218 for (Standard_Integer anI = anIt; anI <= 13; anI++)
219 {
220 myCoeff[anI] = myPrevCoeff[anI];
221 }
222
223 for (Standard_Integer aJ = 0; aJ < 2; aJ++)
224 {
225 myCenter[aJ] = myPrevCenter[aJ];
226 }
227
228 // For orthographic view use only direction of projection and up vector
229 // Panning, and zooming has no effect on 2D selection sensitives.
230 Handle (Graphic3d_Camera) aCamera = new Graphic3d_Camera();
231
232 aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
233 aCamera->SetCenter (gp::Origin());
234 aCamera->SetDirection (gp_Dir (-myCoeff[6], -myCoeff[7], -myCoeff[8]));
235 aCamera->SetUp (gp_Dir (myCoeff[3], myCoeff[4], myCoeff[5]));
236 aCamera->SetDistance (1.0);
237 aCamera->SetAxialScale (gp_XYZ (myCoeff[11], myCoeff[12], myCoeff[13]));
238
239 myPrj = new Select3D_Projector (aCamera->OrientationMatrix(), Graphic3d_Mat4d());
240 }
241
242 if (isPerspective)
243 {
244 if (Abs(theView->GetViewAngle() - aZoom) > 1.e-3)
245 {
246 myToUpdateTol = Standard_True;
247 aZoom = theView->GetViewAngle();
248 }
249 }
250 else
251 {
252 if (Abs (theView->GetParallelScale() - aZoom) > 1.e-3)
253 {
254 myToUpdateTol = Standard_True;
255 aZoom = theView->GetParallelScale();
256 }
257 }
258
259 if(myToUpdateTol)
260 {
261 // Compute and set a sensitivity tolerance according to the view
262 gp_XYZ aWorldPnt1, aWorldPnt2;
263 gp_XY aDispPnt1 (0.0, 0.0);
264 gp_XY aDispPnt2 (myPixTol, 0.0);
265
266 theView->DisplayToWorld (aDispPnt1, aWorldPnt1);
267 theView->DisplayToWorld (aDispPnt2, aWorldPnt2);
268 gp_Pnt aPnt1 (aWorldPnt1);
269 gp_Pnt aPnt2 (aWorldPnt2);
270 SetSensitivity (aPnt2.Distance (aPnt1));
271
272 myToUpdateTol = Standard_False;
273 }
274
275 if(toupdate) UpdateConversion();
276 if(tosort) UpdateSort();
277
278 return Standard_True;
279}
280
281//============================================================================
282// Method: Activate
283// Purpose: Activates the given selection
284//============================================================================
285void IVtkOCC_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection,
286 const Standard_Boolean theIsAutomaticProj)
287{
288 tosort = Standard_True;
289
290 if (!myselections.IsBound (theSelection))
291 {
292 myselections.Bind (theSelection, 0);
293 }
294 else if (myselections (theSelection) != 0)
295 {
296 myselections (theSelection) = 0;
297 }
298 if (theIsAutomaticProj)
299 {
300 Convert (theSelection);
301 }
302}
303
304//============================================================================
305// Method: Deactivate
306// Purpose: Deactivate the given selection
307//============================================================================
308void IVtkOCC_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
309{
310 if (myselections.IsBound (theSelection))
311 {
312 myselections (theSelection) = 1;
313 tosort = Standard_True;
314 }
315}
316
317//============================================================================
318// Method: PickingLine
319// Purpose: Deactivate the given selection
320//============================================================================
321gp_Lin IVtkOCC_ViewerSelector::PickingLine (const Standard_Real theX,const Standard_Real theY) const
322{
323 return myPrj->Shoot (theX, theY);
324}