0024623: Visualization - improve selection mechanism
[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
26   if (theToAllocateFrustums)
27   {
28     mySelectingVolumes[Frustum] = new SelectMgr_RectangularFrustum();
29     mySelectingVolumes[FrustumSet] = new SelectMgr_TriangularFrustumSet();
30   }
31 }
32
33 //=======================================================================
34 // function : Transform
35 // purpose  : Returns a copy of active frustum transformed according to the matrix given
36 //=======================================================================
37 SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::Transform (const gp_Trsf& theTrsf)
38 {
39   SelectMgr_SelectingVolumeManager aMgr (Standard_False);
40
41   if (myActiveSelectionType == Unknown)
42     return aMgr;
43
44   aMgr.myActiveSelectionType = myActiveSelectionType;
45
46   aMgr.mySelectingVolumes[myActiveSelectionType / 2] = mySelectingVolumes[myActiveSelectionType / 2]->Transform (theTrsf);
47
48   return aMgr;
49 }
50
51 //=======================================================================
52 // function : GetActiveSelectionType
53 // purpose  :
54 //=======================================================================
55 const Standard_Integer SelectMgr_SelectingVolumeManager::GetActiveSelectionType() const
56 {
57   return myActiveSelectionType;
58 }
59
60 //=======================================================================
61 // function : SetActiveSelectionType
62 // purpose  :
63 //=======================================================================
64 void SelectMgr_SelectingVolumeManager::SetActiveSelectionType (const SelectionType& theType)
65 {
66   myActiveSelectionType = theType;
67 }
68
69 //=======================================================================
70 // function : SetCamera
71 // purpose  : Updates camera projection and orientation matrices in all
72 //            selecting volumes
73 //=======================================================================
74 void SelectMgr_SelectingVolumeManager::SetCamera (const Handle(Graphic3d_Camera) theCamera)
75 {
76   for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
77   {
78     mySelectingVolumes[anIdx]->SetCamera (theCamera);
79   }
80 }
81
82 //=======================================================================
83 // function : SetCamera
84 // purpose  : Updates camera projection and orientation matrices in all
85 //            selecting volumes
86 //=======================================================================
87 void SelectMgr_SelectingVolumeManager::SetCamera (const Graphic3d_Mat4d& theProjection,
88                                                   const Graphic3d_Mat4d& theOrientation,
89                                                   const Standard_Boolean theIsOrthographic)
90 {
91   for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
92   {
93     mySelectingVolumes[anIdx]->SetCamera (theProjection, theOrientation, theIsOrthographic);
94   }
95 }
96
97 //=======================================================================
98 // function : SetCamera
99 // purpose  : Updates viewport in all selecting volumes
100 //=======================================================================
101 void SelectMgr_SelectingVolumeManager::SetViewport (const Standard_Real theX,
102                                                     const Standard_Real theY,
103                                                     const Standard_Real theWidth,
104                                                     const Standard_Real theHeight)
105 {
106   for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
107   {
108     mySelectingVolumes[anIdx]->SetViewport (theX, theY, theWidth, theHeight);
109   }
110 }
111
112 //=======================================================================
113 // function : SetWindowSize
114 // purpose  : Updates window size in all selecting volumes
115 //=======================================================================
116 void SelectMgr_SelectingVolumeManager::SetWindowSize (const Standard_Integer theWidth,
117                                                       const Standard_Integer theHeight)
118 {
119   for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
120   {
121     mySelectingVolumes[anIdx]->SetWindowSize (theWidth, theHeight);
122   }
123 }
124
125 //=======================================================================
126 // function : SetPixelTolerance
127 // purpose  : Updates pixel tolerance in all selecting volumes
128 //=======================================================================
129 void SelectMgr_SelectingVolumeManager::SetPixelTolerance (const Standard_Real theTolerance)
130 {
131   for (Standard_Integer anIdx = 0; anIdx < VolumeTypesNb; ++anIdx)
132   {
133     mySelectingVolumes[anIdx]->SetPixelTolerance (theTolerance);
134   }
135 }
136
137 //=======================================================================
138 // function : BuildSelectingVolume
139 // purpose  : Builds rectangular selecting frustum for point selection
140 //=======================================================================
141 void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const gp_Pnt2d& thePoint)
142 {
143   if (myActiveSelectionType != Point)
144     return;
145
146   mySelectingVolumes[Frustum]->Build (thePoint);
147 }
148
149 //=======================================================================
150 // function : BuildSelectingVolume
151 // purpose  : Builds rectangular selecting frustum for box selection
152 //=======================================================================
153 void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const gp_Pnt2d& theMinPt,
154                                                              const gp_Pnt2d& theMaxPt)
155 {
156   if (myActiveSelectionType != Box)
157     return;
158
159   mySelectingVolumes[Frustum]->Build (theMinPt, theMaxPt);
160 }
161
162 //=======================================================================
163 // function : BuildSelectingVolume
164 // purpose  : Builds set of triangular selecting frustums for polyline
165 //            selection
166 //=======================================================================
167 void SelectMgr_SelectingVolumeManager::BuildSelectingVolume (const TColgp_Array1OfPnt2d& thePoints)
168 {
169   if (myActiveSelectionType != Polyline)
170     return;
171
172   mySelectingVolumes[FrustumSet]->Build (thePoints);
173 }
174
175 //=======================================================================
176 // function : Overlaps
177 // purpose  : SAT intersection test between defined volume and
178 //            given axis-aligned box
179 //=======================================================================
180 const Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const BVH_Box<Standard_Real, 3>& theBndBox,
181                                                                    Standard_Real& theDepth)
182 {
183   if (myActiveSelectionType == Unknown)
184     return Standard_False;
185
186   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theBndBox,
187                                                                   theDepth);
188 }
189
190 //=======================================================================
191 // function : Overlaps
192 // purpose  : Intersection test between defined volume and given point
193 //=======================================================================
194 const Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const SelectMgr_Vec3& theMinPt,
195                                                                    const SelectMgr_Vec3& theMaxPt)
196 {
197   if (myActiveSelectionType == Unknown)
198     return Standard_False;
199
200   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theMinPt, theMaxPt);
201 }
202
203 //=======================================================================
204 // function : Overlaps
205 // purpose  : Intersection test between defined volume and given point
206 //=======================================================================
207 const Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt,
208                                                                    Standard_Real& theDepth)
209 {
210   if (myActiveSelectionType == Unknown)
211     return Standard_False;
212
213   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePt,
214                                                                   theDepth);
215 }
216
217 //=======================================================================
218 // function : Overlaps
219 // purpose  : SAT intersection test between defined volume and given
220 //            ordered set of points, representing line segments. The test
221 //            may be considered of interior part or boundary line defined
222 //            by segments depending on given sensitivity type
223 //=======================================================================
224 const Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts,
225                                                                    Standard_Integer theSensType,
226                                                                    Standard_Real& theDepth)
227 {
228   if (myActiveSelectionType == Unknown)
229     return Standard_False;
230
231   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPts,
232                                                                   (Select3D_TypeOfSensitivity)theSensType,
233                                                                   theDepth);
234 }
235
236 //=======================================================================
237 // function : Overlaps
238 // purpose  : Checks if line segment overlaps selecting volume
239 //=======================================================================
240 const Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt1,
241                                                                    const gp_Pnt& thePt2,
242                                                                    Standard_Real& theDepth)
243 {
244   if (myActiveSelectionType == Unknown)
245     return Standard_False;
246
247   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePt1, thePt2, theDepth);
248 }
249
250 //=======================================================================
251 // function : Overlaps
252 // purpose  : SAT intersection test between defined volume and given
253 //            triangle. The test may be considered of interior part or
254 //            boundary line defined by triangle vertices depending on
255 //            given sensitivity type
256 //=======================================================================
257 const Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const gp_Pnt& thePt1,
258                                                                    const gp_Pnt& thePt2,
259                                                                    const gp_Pnt& thePt3,
260                                                                    Standard_Integer theSensType,
261                                                                    Standard_Real& theDepth)
262 {
263   if (myActiveSelectionType == Unknown)
264     return Standard_False;
265
266   return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (thePt1,
267                                                                   thePt2,
268                                                                   thePt3,
269                                                                   (Select3D_TypeOfSensitivity)theSensType,
270                                                                   theDepth);
271 }
272
273 //=======================================================================
274 // function : DistToGeometryCenter
275 // purpose  : Measures distance between 3d projection of user-picked
276 //            screen point and given point theCOG
277 //=======================================================================
278 const Standard_Real SelectMgr_SelectingVolumeManager::DistToGeometryCenter (const gp_Pnt& theCOG)
279 {
280   if (myActiveSelectionType == Unknown)
281     return Standard_False;
282
283   return mySelectingVolumes[myActiveSelectionType / 2]->DistToGeometryCenter (theCOG);
284 }
285
286 // =======================================================================
287 // function : DetectedPoint
288 // purpose  : Calculates the point on a view ray that was detected during
289 //            the run of selection algo by given depth. Is valid for point
290 //            selection only
291 // =======================================================================
292 NCollection_Vec3<Standard_Real> SelectMgr_SelectingVolumeManager::DetectedPoint (const Standard_Real theDepth) const
293 {
294   if (myActiveSelectionType != Point)
295     return NCollection_Vec3<Standard_Real> (RealLast());
296
297   return mySelectingVolumes[Frustum]->DetectedPoint (theDepth);
298 }
299
300 //=======================================================================
301 // function : IsClipped
302 // purpose  : Checks if the point of sensitive in which selection was
303 //            detected belongs to the region defined by clipping planes
304 //=======================================================================
305 const Standard_Boolean SelectMgr_SelectingVolumeManager::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
306                                                                     const Standard_Real& theDepth)
307 {
308   if (myActiveSelectionType == Point)
309     return Standard_False;
310
311   return mySelectingVolumes[Frustum]->IsClipped (thePlanes, theDepth);
312 }