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