0029938: Visualization - SelectMgr_ViewerSelector::PickedPoint() should return point...
[occt.git] / src / SelectMgr / SelectMgr_SelectingVolumeManager.cxx
1 // Created on: 2014-05-22
2 // Created by: Varvara POSKONINA
3 // Copyright (c) 2005-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 <SelectMgr_SelectingVolumeManager.hxx>
17
18 //=======================================================================
19 // function : SelectMgr_SelectingVolumeManager
20 // purpose  : Creates instances of all available selecting volume types
21 //=======================================================================
22 SelectMgr_SelectingVolumeManager::SelectMgr_SelectingVolumeManager (Standard_Boolean theToAllocateFrustums)
23 {
24   myActiveSelectionType = Unknown;
25   myToAllowOverlap = Standard_False;
26
27   if (theToAllocateFrustums)
28   {
29     mySelectingVolumes[Frustum] = new SelectMgr_RectangularFrustum();
30     mySelectingVolumes[FrustumSet] = new SelectMgr_TriangularFrustumSet();
31   }
32 }
33
34 //=======================================================================
35 // function : ScaleAndTransform
36 // purpose  : IMPORTANT: Scaling makes sense only for frustum built on a single point!
37 //            Note that this method does not perform any checks on type of the frustum.
38 //
39 //            Returns a copy of the frustum resized according to the scale factor given
40 //            and transforms it using the matrix given.
41 //            There are no default parameters, but in case if:
42 //                - transformation only is needed: @theScaleFactor must be initialized
43 //                  as any negative value;
44 //                - scale only is needed: @theTrsf must be set to gp_Identity.
45 //            Builder is an optional argument that represents corresponding settings for
46 //            re-constructing transformed frustum from scratch. Can be null if reconstruction
47 //            is not needed furthermore in the code.
48 //=======================================================================
49 SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::ScaleAndTransform (const Standard_Integer theScaleFactor,
50                                                                                       const gp_GTrsf& theTrsf,
51                                                                                       const Handle(SelectMgr_FrustumBuilder)& theBuilder) const
52 {
53   SelectMgr_SelectingVolumeManager aMgr (Standard_False);
54
55   if (myActiveSelectionType == Unknown)
56     return aMgr;
57
58   aMgr.myActiveSelectionType = myActiveSelectionType;
59   aMgr.mySelectingVolumes[myActiveSelectionType / 2]
60     = mySelectingVolumes[myActiveSelectionType / 2]->ScaleAndTransform (theScaleFactor, theTrsf);
61   aMgr.myToAllowOverlap = myToAllowOverlap;
62   aMgr.mySelectingVolumes[myActiveSelectionType / 2]->SetBuilder (theBuilder);
63   aMgr.myViewClipPlanes = myViewClipPlanes;
64
65   return aMgr;
66 }
67
68 //=======================================================================
69 // function : GetActiveSelectionType
70 // purpose  :
71 //=======================================================================
72 Standard_Integer SelectMgr_SelectingVolumeManager::GetActiveSelectionType() const
73 {
74   return myActiveSelectionType;
75 }
76
77 //=======================================================================
78 // function : SetActiveSelectionType
79 // purpose  :
80 //=======================================================================
81 void SelectMgr_SelectingVolumeManager::SetActiveSelectionType (const SelectionType& theType)
82 {
83   myActiveSelectionType = theType;
84 }
85
86 //=======================================================================
87 // function : SetCamera
88 // purpose  : Updates camera projection and orientation matrices in all
89 //            selecting volumes
90 //=======================================================================
91 void SelectMgr_SelectingVolumeManager::SetCamera (const Handle(Graphic3d_Camera) theCamera)
92 {
93   for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
94   {
95     mySelectingVolumes[anIdx]->SetCamera (theCamera);
96   }
97 }
98
99 //=======================================================================
100 // function : SetCamera
101 // purpose  : Updates camera projection and orientation matrices in all
102 //            selecting volumes
103 //=======================================================================
104 void SelectMgr_SelectingVolumeManager::SetCamera (const Graphic3d_Mat4d& theProjection,
105                                                   const Graphic3d_Mat4d& theWorldView,
106                                                   const Standard_Boolean theIsOrthographic,
107                                                   const Graphic3d_WorldViewProjState& theWVPState)
108 {
109   for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
110   {
111     mySelectingVolumes[anIdx]->SetCamera (theProjection, theWorldView, theIsOrthographic, theWVPState);
112   }
113 }
114
115 //=======================================================================
116 // function : ProjectionMatrix
117 // purpose  : Returns current projection transformation common for all
118 //            selecting volumes
119 //=======================================================================
120 const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::ProjectionMatrix() const
121 {
122   return mySelectingVolumes[Frustum]->ProjectionMatrix();
123 }
124
125 //=======================================================================
126 // function : WorldViewMatrix
127 // purpose  : Returns current world view transformation common for all
128 //            selecting volumes
129 //=======================================================================
130 const Graphic3d_Mat4d& SelectMgr_SelectingVolumeManager::WorldViewMatrix() const
131 {
132   return mySelectingVolumes[Frustum]->WorldViewMatrix();
133 }
134
135 //=======================================================================
136 // function : WorldViewProjState
137 // purpose  : Returns current camera world view projection transformation
138 //            state common for all selecting volumes
139 //=======================================================================
140 const Graphic3d_WorldViewProjState& SelectMgr_SelectingVolumeManager::WorldViewProjState() const
141 {
142   return mySelectingVolumes[Frustum]->WorldViewProjState();
143 }
144
145 //=======================================================================
146 // function : WindowSize
147 // purpose  :
148 //=======================================================================
149 void SelectMgr_SelectingVolumeManager::WindowSize (Standard_Integer& theWidth, Standard_Integer& theHeight) const
150 {
151   mySelectingVolumes[Frustum]->WindowSize (theWidth, theHeight);
152 }
153
154 //=======================================================================
155 // function : SetCamera
156 // purpose  : Updates viewport in all selecting volumes
157 //=======================================================================
158 void SelectMgr_SelectingVolumeManager::SetViewport (const Standard_Real theX,
159                                                     const Standard_Real theY,
160                                                     const Standard_Real theWidth,
161                                                     const Standard_Real theHeight)
162 {
163   for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
164   {
165     mySelectingVolumes[anIdx]->SetViewport (theX, theY, theWidth, theHeight);
166   }
167 }
168
169 //=======================================================================
170 // function : SetWindowSize
171 // purpose  : Updates window size in all selecting volumes
172 //=======================================================================
173 void SelectMgr_SelectingVolumeManager::SetWindowSize (const Standard_Integer theWidth,
174                                                       const Standard_Integer theHeight)
175 {
176   for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
177   {
178     mySelectingVolumes[anIdx]->SetWindowSize (theWidth, theHeight);
179   }
180 }
181
182 //=======================================================================
183 // function : SetPixelTolerance
184 // purpose  : Updates pixel tolerance in all selecting volumes
185 //=======================================================================
186 void SelectMgr_SelectingVolumeManager::SetPixelTolerance (const Standard_Integer theTolerance)
187 {
188   for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
189   {
190     mySelectingVolumes[anIdx]->SetPixelTolerance (theTolerance);
191   }
192 }
193
194 //=======================================================================
195 // function : BuildSelectingVolume
196 // purpose  : Builds rectangular selecting frustum for point selection
197 //=======================================================================
198 void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const gp_Pnt2d& thePoint)
199 {
200   if (myActiveSelectionType != Point)
201     return;
202
203   mySelectingVolumes[Frustum]->Build (thePoint);
204 }
205
206 //=======================================================================
207 // function : BuildSelectingVolume
208 // purpose  : Builds rectangular selecting frustum for box selection
209 //=======================================================================
210 void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const gp_Pnt2d& theMinPt,
211                                                              const gp_Pnt2d& theMaxPt)
212 {
213   if (myActiveSelectionType != Box)
214     return;
215
216   mySelectingVolumes[Frustum]->Build (theMinPt, theMaxPt);
217 }
218
219 //=======================================================================
220 // function : BuildSelectingVolume
221 // purpose  : Builds set of triangular selecting frustums for polyline
222 //            selection
223 //=======================================================================
224 void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const TColgp_Array1OfPnt2d& thePoints)
225 {
226   if (myActiveSelectionType != Polyline)
227     return;
228
229   mySelectingVolumes[FrustumSet]->Build (thePoints);
230 }
231
232 //=======================================================================
233 // function : Overlaps
234 // purpose  : SAT intersection test between defined volume and
235 //            given axis-aligned box
236 //=======================================================================
237 Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec3& theBoxMin,
238                                                              const SelectMgr_Vec3& theBoxMax,
239                                                              SelectBasics_PickResult& thePickResult)
240 {
241   if (myActiveSelectionType == Unknown)
242     return Standard_False;
243
244   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBoxMin, theBoxMax, thePickResult);
245 }
246
247 //=======================================================================
248 // function : Overlaps
249 // purpose  : Intersection test between defined volume and given point
250 //=======================================================================
251 Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec3& theBoxMin,
252                                                              const SelectMgr_Vec3& theBoxMax,
253                                                              Standard_Boolean*     theInside)
254 {
255   if (myActiveSelectionType == Unknown)
256     return Standard_False;
257
258   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBoxMin, theBoxMax, theInside);
259 }
260
261 //=======================================================================
262 // function : Overlaps
263 // purpose  : Intersection test between defined volume and given point
264 //=======================================================================
265 Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePnt,
266                                                              SelectBasics_PickResult& thePickResult)
267 {
268   if (myActiveSelectionType == Unknown)
269     return Standard_False;
270
271   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePnt,
272                                                                   thePickResult);
273 }
274
275 //=======================================================================
276 // function : Overlaps
277 // purpose  : Intersection test between defined volume and given point
278 //=======================================================================
279 Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePnt)
280 {
281   if (myActiveSelectionType == Unknown)
282     return Standard_False;
283
284   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePnt);
285 }
286
287 //=======================================================================
288 // function : Overlaps
289 // purpose  : SAT intersection test between defined volume and given
290 //            ordered set of points, representing line segments. The test
291 //            may be considered of interior part or boundary line defined
292 //            by segments depending on given sensitivity type
293 //=======================================================================
294 Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
295                                                              Standard_Integer theSensType,
296                                                              SelectBasics_PickResult& thePickResult)
297 {
298   if (myActiveSelectionType == Unknown)
299     return Standard_False;
300
301   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPnts->Array1(),
302                                                                   (Select3D_TypeOfSensitivity)theSensType,
303                                                                   thePickResult);
304 }
305
306 //=======================================================================
307 // function : Overlaps
308 // purpose  : SAT intersection test between defined volume and given
309 //            ordered set of points, representing line segments. The test
310 //            may be considered of interior part or boundary line defined
311 //            by segments depending on given sensitivity type
312 //=======================================================================
313 Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts,
314                                                              Standard_Integer theSensType,
315                                                              SelectBasics_PickResult& thePickResult)
316 {
317   if (myActiveSelectionType == Unknown)
318     return Standard_False;
319
320   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPnts,
321                                                                   (Select3D_TypeOfSensitivity)theSensType,
322                                                                   thePickResult);
323 }
324
325 //=======================================================================
326 // function : Overlaps
327 // purpose  : Checks if line segment overlaps selecting volume
328 //=======================================================================
329 Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt1,
330                                                              const gp_Pnt& thePt2,
331                                                              SelectBasics_PickResult& thePickResult)
332 {
333   if (myActiveSelectionType == Unknown)
334     return Standard_False;
335
336   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePt1, thePt2, thePickResult);
337 }
338
339 //=======================================================================
340 // function : Overlaps
341 // purpose  : SAT intersection test between defined volume and given
342 //            triangle. The test may be considered of interior part or
343 //            boundary line defined by triangle vertices depending on
344 //            given sensitivity type
345 //=======================================================================
346 Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt1,
347                                                              const gp_Pnt& thePt2,
348                                                              const gp_Pnt& thePt3,
349                                                              Standard_Integer theSensType,
350                                                              SelectBasics_PickResult& thePickResult)
351 {
352   if (myActiveSelectionType == Unknown)
353     return Standard_False;
354
355   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePt1,
356                                                                   thePt2,
357                                                                   thePt3,
358                                                                   (Select3D_TypeOfSensitivity)theSensType,
359                                                                   thePickResult);
360 }
361
362 //=======================================================================
363 // function : DistToGeometryCenter
364 // purpose  : Measures distance between 3d projection of user-picked
365 //            screen point and given point theCOG
366 //=======================================================================
367 Standard_Real SelectMgr_SelectingVolumeManager::DistToGeometryCenter (const gp_Pnt& theCOG)
368 {
369   if (myActiveSelectionType == Unknown)
370     return Standard_False;
371
372   return mySelectingVolumes[myActiveSelectionType / 2]->DistToGeometryCenter (theCOG);
373 }
374
375 // =======================================================================
376 // function : DetectedPoint
377 // purpose  : Calculates the point on a view ray that was detected during
378 //            the run of selection algo by given depth. Is valid for point
379 //            selection only
380 // =======================================================================
381 gp_Pnt SelectMgr_SelectingVolumeManager::DetectedPoint (const Standard_Real theDepth) const
382 {
383   if (myActiveSelectionType != Point)
384   {
385     throw Standard_ProgramError("SelectMgr_SelectingVolumeManager::DetectedPoint() should be called only for Point selection type");
386   }
387
388   return mySelectingVolumes[Frustum]->DetectedPoint (theDepth);
389 }
390
391 //=======================================================================
392 // function : IsClipped
393 // purpose  : Checks if the point of sensitive in which selection was
394 //            detected belongs to the region defined by clipping planes
395 //=======================================================================
396 Standard_Boolean SelectMgr_SelectingVolumeManager::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
397                                                               const Standard_Real& theDepth)
398 {
399   if (myActiveSelectionType != Point)
400     return Standard_False;
401
402   return mySelectingVolumes[Frustum]->IsClipped (thePlanes, theDepth);
403 }
404
405 //=======================================================================
406 // function : AllowOverlapDetection
407 // purpose  : If theIsToAllow is false, only fully included sensitives will
408 //            be detected, otherwise the algorithm will mark both included
409 //            and overlapped entities as matched
410 //=======================================================================
411 void SelectMgr_SelectingVolumeManager::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
412 {
413   myToAllowOverlap = theIsToAllow;
414 }
415
416 //=======================================================================
417 // function : IsOverlapAllowed
418 // purpose  :
419 //=======================================================================
420 Standard_Boolean SelectMgr_SelectingVolumeManager::IsOverlapAllowed() const
421 {
422   return myActiveSelectionType != Box || myToAllowOverlap;
423 }
424
425 //=======================================================================
426 // function : GetVertices
427 // purpose  :
428 //=======================================================================
429 const gp_Pnt* SelectMgr_SelectingVolumeManager::GetVertices() const
430 {
431   if (myActiveSelectionType == Polyline)
432     return NULL;
433
434   const SelectMgr_RectangularFrustum* aFr =
435     reinterpret_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get());
436   return aFr->GetVertices();
437 }
438
439 //=======================================================================
440 // function : GetNearPickedPnt
441 // purpose  :
442 //=======================================================================
443 gp_Pnt SelectMgr_SelectingVolumeManager::GetNearPickedPnt() const
444 {
445   if (myActiveSelectionType == Polyline)
446     return gp_Pnt();
447
448    const SelectMgr_RectangularFrustum* aFr =
449      reinterpret_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get());
450   return aFr->GetNearPnt();
451 }
452
453 //=======================================================================
454 // function : GetFarPickedPnt
455 // purpose  :
456 //=======================================================================
457 gp_Pnt SelectMgr_SelectingVolumeManager::GetFarPickedPnt() const
458 {
459   if (myActiveSelectionType == Polyline)
460     return gp_Pnt();
461
462    const SelectMgr_RectangularFrustum* aFr =
463      reinterpret_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get());
464   return aFr->GetFarPnt();
465 }
466
467 //=======================================================================
468 // function : SetViewClipping
469 // purpose  :
470 //=======================================================================
471 void SelectMgr_SelectingVolumeManager::SetViewClipping (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes)
472 {
473   myViewClipPlanes = thePlanes;
474   if (myActiveSelectionType != Point)
475     return;
476
477   mySelectingVolumes[Frustum]->SetViewClipping (thePlanes);
478 }
479
480 //=======================================================================
481 // function : SetViewClippingEnabled
482 // purpose  :
483 //=======================================================================
484 Standard_Boolean SelectMgr_SelectingVolumeManager::SetViewClippingEnabled (const Standard_Boolean theToEnable)
485 {
486   if (myActiveSelectionType != Point)
487     return Standard_False;
488
489   return mySelectingVolumes[Frustum]->SetViewClippingEnabled (theToEnable);
490 }