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