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