0029938: Visualization - SelectMgr_ViewerSelector::PickedPoint() should return point...
[occt.git] / src / Select3D / Select3D_SensitiveSet.cxx
1 // Created on: 2014-05-29
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 <Select3D_SensitiveSet.hxx>
17
18 #include <BVH_LinearBuilder.hxx>
19
20 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveSet,Select3D_SensitiveEntity)
21
22 namespace
23 {
24   //! Default BVH tree builder for sensitive set (optimal for large set of small primitives - for not too long construction time).
25   static Handle(Select3D_BVHBuilder3d) THE_SENS_SET_BUILDER = new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeSmall, BVH_Constants_MaxTreeDepth);
26 }
27
28 //=======================================================================
29 // function : DefaultBVHBuilder
30 // purpose  :
31 //=======================================================================
32 const Handle(Select3D_BVHBuilder3d)& Select3D_SensitiveSet::DefaultBVHBuilder()
33 {
34   return THE_SENS_SET_BUILDER;
35 }
36
37 //=======================================================================
38 // function : SetDefaultBVHBuilder
39 // purpose  :
40 //=======================================================================
41 void Select3D_SensitiveSet::SetDefaultBVHBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
42 {
43   THE_SENS_SET_BUILDER = theBuilder;
44 }
45
46 //=======================================================================
47 // function : Select3D_SensitiveSet
48 // purpose  : Creates new empty sensitive set and its content
49 //=======================================================================
50 Select3D_SensitiveSet::Select3D_SensitiveSet (const Handle(SelectBasics_EntityOwner)& theOwnerId)
51 : Select3D_SensitiveEntity (theOwnerId),
52   myDetectedIdx (-1)
53 {
54   myContent.SetSensitiveSet (this);
55   myContent.SetBuilder (THE_SENS_SET_BUILDER);
56   myContent.MarkDirty();
57 }
58
59 //=======================================================================
60 // function : BVH
61 // purpose  : Builds BVH tree for sensitive set
62 //=======================================================================
63 void Select3D_SensitiveSet::BVH()
64 {
65   myContent.GetBVH();
66 }
67
68 //=======================================================================
69 // function : Matches
70 // purpose  : Checks whether one or more entities of the set overlap
71 //            current selecting volume. Implements the traverse of BVH
72 //            tree built for the set
73 //=======================================================================
74 Standard_Boolean Select3D_SensitiveSet::Matches (SelectBasics_SelectingVolumeManager& theMgr,
75                                                  SelectBasics_PickResult& thePickResult)
76 {
77   myDetectedIdx = -1;
78   const BVH_Tree<Standard_Real, 3, BVH_BinaryTree>* aBVH = myContent.GetBVH().get();
79   if (myContent.Size() < 1 || !theMgr.Overlaps (aBVH->MinPoint (0),
80                                                 aBVH->MaxPoint (0)))
81   {
82     return Standard_False;
83   }
84
85   Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
86   Standard_Integer aNode =  0;
87   Standard_Integer aHead = -1;
88
89   Standard_Integer aMatchesNb = -1;
90   SelectBasics_PickResult aPickResult;
91   for (;;)
92   {
93     const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode];
94
95     if (aData.x() == 0) // is inner node
96     {
97       const Standard_Integer aLftIdx = aData.y();
98       const Standard_Integer aRghIdx = aData.z();
99
100       Standard_Boolean isLftInside = Standard_True;
101       Standard_Boolean isRghInside = Standard_True;
102
103       Standard_Boolean toCheckLft = theMgr.Overlaps (aBVH->MinPoint (aLftIdx),
104                                                      aBVH->MaxPoint (aLftIdx),
105                                                      theMgr.IsOverlapAllowed() ? NULL : &isLftInside);
106
107       Standard_Boolean toCheckRgh = theMgr.Overlaps (aBVH->MinPoint (aRghIdx),
108                                                      aBVH->MaxPoint (aRghIdx),
109                                                      theMgr.IsOverlapAllowed() ? NULL : &isRghInside);
110
111       if (!theMgr.IsOverlapAllowed()) // inclusion test
112       {
113         if (!toCheckLft || !toCheckRgh)
114         {
115           return Standard_False; // no inclusion
116         }
117
118         toCheckLft &= !isLftInside;
119         toCheckRgh &= !isRghInside;
120       }
121
122       if (toCheckLft || toCheckRgh)
123       {
124         aNode = toCheckLft ? aLftIdx : aRghIdx;
125
126         if (toCheckLft && toCheckRgh)
127         {
128           aStack[++aHead] = aRghIdx;
129         }
130       }
131       else
132       {
133         if (aHead < 0)
134           break;
135
136         aNode = aStack[aHead--];
137       }
138     }
139     else
140     {
141       for (Standard_Integer anElemIdx = aData.y(); anElemIdx <= aData.z(); ++anElemIdx)
142       {
143         if (!theMgr.IsOverlapAllowed()) // inclusion test
144         {
145           if (!elementIsInside (theMgr, anElemIdx))
146           {
147             return Standard_False;
148           }
149         }
150         else // overlap test
151         {
152           if (!overlapsElement (theMgr, anElemIdx, aPickResult))
153           {
154             continue;
155           }
156
157           if (thePickResult.Depth() > aPickResult.Depth())
158           {
159             thePickResult = aPickResult;
160             myDetectedIdx = anElemIdx;
161           }
162
163           ++aMatchesNb;
164         }
165       }
166
167       if (aHead < 0)
168         break;
169
170       aNode = aStack[aHead--];
171     }
172   }
173
174   if (aMatchesNb != -1)
175   {
176     thePickResult.SetDistToGeomCenter(distanceToCOG(theMgr));
177   }
178
179   return !theMgr.IsOverlapAllowed() || aMatchesNb != -1;
180 }
181
182 //=======================================================================
183 // function : BoundingBox
184 // purpose  : This method should be redefined in Select3D_SensitiveSet
185 //            descendants
186 //=======================================================================
187 Select3D_BndBox3d Select3D_SensitiveSet::BoundingBox()
188 {
189   return Select3D_BndBox3d (SelectMgr_Vec3 (RealLast()),
190                             SelectMgr_Vec3 (RealFirst()));
191 }
192
193 //=======================================================================
194 // function : CenterOfGeometry
195 // purpose  : This method should be redefined in Select3D_SensitiveSet
196 //            descendants
197 //=======================================================================
198 gp_Pnt Select3D_SensitiveSet::CenterOfGeometry() const
199 {
200   return gp_Pnt (RealLast(), RealLast(), RealLast());
201 }
202
203 //=======================================================================
204 // function : Clear
205 // purpose  : Destroys cross-reference to avoid memory leak
206 //=======================================================================
207 void Select3D_SensitiveSet::Clear()
208 {
209   //
210 }