be810f005035d02982be0b06b2105746908d19cc
[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   const BVH_Tree<Standard_Real, 3, BVH_BinaryTree>* aBVH = myContent.GetBVH().get();
78
79   thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
80
81   if (myContent.Size() < 1 || !theMgr.Overlaps (aBVH->MinPoint (0),
82                                                 aBVH->MaxPoint (0)))
83   {
84     return Standard_False;
85   }
86
87   Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
88   Standard_Integer aNode =  0;
89   Standard_Integer aHead = -1;
90
91   Standard_Integer aMatchesNb = -1;
92   Standard_Real    aMinDepth  = RealLast();
93
94   for (;;)
95   {
96     const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode];
97
98     if (aData.x() == 0) // is inner node
99     {
100       const Standard_Integer aLftIdx = aData.y();
101       const Standard_Integer aRghIdx = aData.z();
102
103       Standard_Boolean isLftInside = Standard_True;
104       Standard_Boolean isRghInside = Standard_True;
105
106       Standard_Boolean toCheckLft = theMgr.Overlaps (aBVH->MinPoint (aLftIdx),
107                                                      aBVH->MaxPoint (aLftIdx),
108                                                      theMgr.IsOverlapAllowed() ? NULL : &isLftInside);
109
110       Standard_Boolean toCheckRgh = theMgr.Overlaps (aBVH->MinPoint (aRghIdx),
111                                                      aBVH->MaxPoint (aRghIdx),
112                                                      theMgr.IsOverlapAllowed() ? NULL : &isRghInside);
113
114       if (!theMgr.IsOverlapAllowed()) // inclusion test
115       {
116         if (!toCheckLft || !toCheckRgh)
117         {
118           return Standard_False; // no inclusion
119         }
120
121         toCheckLft &= !isLftInside;
122         toCheckRgh &= !isRghInside;
123       }
124
125       if (toCheckLft || toCheckRgh)
126       {
127         aNode = toCheckLft ? aLftIdx : aRghIdx;
128
129         if (toCheckLft && toCheckRgh)
130         {
131           aStack[++aHead] = aRghIdx;
132         }
133       }
134       else
135       {
136         if (aHead < 0)
137           break;
138
139         aNode = aStack[aHead--];
140       }
141     }
142     else
143     {
144       for (Standard_Integer anElemIdx = aData.y(); anElemIdx <= aData.z(); ++anElemIdx)
145       {
146         if (!theMgr.IsOverlapAllowed()) // inclusion test
147         {
148           if (!elementIsInside (theMgr, anElemIdx))
149           {
150             return Standard_False;
151           }
152         }
153         else // overlap test
154         {
155           Standard_Real aCurrentDepth = aMinDepth;
156
157           if (!overlapsElement (theMgr, anElemIdx, aCurrentDepth))
158           {
159             continue;
160           }
161
162           if (aMinDepth > aCurrentDepth)
163           {
164             aMinDepth = aCurrentDepth;
165             myDetectedIdx = anElemIdx;
166           }
167
168           ++aMatchesNb;
169         }
170       }
171
172       if (aHead < 0)
173         break;
174
175       aNode = aStack[aHead--];
176     }
177   }
178
179   if (aMatchesNb != -1)
180   {
181     thePickResult = SelectBasics_PickResult (aMinDepth, distanceToCOG (theMgr));
182   }
183
184   return !theMgr.IsOverlapAllowed() || aMatchesNb != -1;
185 }
186
187 //=======================================================================
188 // function : BoundingBox
189 // purpose  : This method should be redefined in Select3D_SensitiveSet
190 //            descendants
191 //=======================================================================
192 Select3D_BndBox3d Select3D_SensitiveSet::BoundingBox()
193 {
194   return Select3D_BndBox3d (SelectMgr_Vec3 (RealLast()),
195                             SelectMgr_Vec3 (RealFirst()));
196 }
197
198 //=======================================================================
199 // function : CenterOfGeometry
200 // purpose  : This method should be redefined in Select3D_SensitiveSet
201 //            descendants
202 //=======================================================================
203 gp_Pnt Select3D_SensitiveSet::CenterOfGeometry() const
204 {
205   return gp_Pnt (RealLast(), RealLast(), RealLast());
206 }
207
208 //=======================================================================
209 // function : Clear
210 // purpose  : Destroys cross-reference to avoid memory leak
211 //=======================================================================
212 void Select3D_SensitiveSet::Clear()
213 {
214   //
215 }