ed9b8b30ecf26dea48de52cd7307cb4a9b63b458
[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 IMPLEMENT_STANDARD_HANDLE (Select3D_SensitiveSet, Select3D_SensitiveEntity)
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> >& aBVHTree = myContent->GetBVH();
53
54   Standard_Integer aNode = 0; // a root node
55   if (!theMgr.Overlaps (aBVHTree->MinPoint (0),
56                         aBVHTree->MaxPoint (0)))
57   {
58     return Standard_False;
59   }
60
61   Standard_Integer aStack[32];
62   Standard_Integer aHead = -1;
63   Standard_Real aDepth      = RealLast();
64   Standard_Real aDistToCOG  = RealLast();
65   SelectMgr_Vec3 aClosestPnt (RealLast());
66   Standard_Integer aMatchesNb = -1;
67   for (;;)
68   {
69     if (!aBVHTree->IsOuter (aNode))
70     {
71       const Standard_Integer aLeftChildIdx  = aBVHTree->LeftChild  (aNode);
72       const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
73       const Standard_Boolean isLeftChildIn  = theMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx),
74                                                                aBVHTree->MaxPoint (aLeftChildIdx));
75       const Standard_Boolean isRightChildIn = theMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx),
76                                                                aBVHTree->MaxPoint (aRightChildIdx));
77       if (isLeftChildIn
78        && isRightChildIn)
79       {
80         aNode = aLeftChildIdx;
81         ++aHead;
82         aStack[aHead] = aRightChildIdx;
83       }
84       else if (isLeftChildIn
85             || isRightChildIn)
86       {
87         aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
88       }
89       else
90       {
91         if (aHead < 0)
92         {
93           break;
94         }
95
96         aNode = aStack[aHead];
97         --aHead;
98       }
99     }
100     else
101     {
102       Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
103       Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
104       Standard_Boolean isMatched = Standard_False;
105       for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
106       {
107         Standard_Real anElementDepth = 0.0;
108         isMatched = overlapsElement (theMgr, anIdx, anElementDepth);
109         if (isMatched)
110         {
111           if (aDepth > anElementDepth)
112           {
113             aDepth = anElementDepth;
114             myDetectedIdx = anIdx;
115           }
116           aMatchesNb++;
117         }
118       }
119       if (aHead < 0)
120       {
121         break;
122       }
123
124       aNode = aStack[aHead];
125       --aHead;
126     }
127   }
128
129   if (aMatchesNb != -1)
130   {
131     aDistToCOG = distanceToCOG (theMgr);
132     thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
133     return Standard_True;
134   }
135
136   thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
137   return Standard_False;
138 }
139
140 //=======================================================================
141 // function : BoundingBox
142 // purpose  : This method should be redefined in Select3D_SensitiveSet
143 //            descendants
144 //=======================================================================
145 Select3D_BndBox3d Select3D_SensitiveSet::BoundingBox()
146 {
147   return Select3D_BndBox3d (SelectMgr_Vec3 (RealLast()),
148                             SelectMgr_Vec3 (RealFirst()));
149 }
150
151 //=======================================================================
152 // function : CenterOfGeometry
153 // purpose  : This method should be redefined in Select3D_SensitiveSet
154 //            descendants
155 //=======================================================================
156 gp_Pnt Select3D_SensitiveSet::CenterOfGeometry() const
157 {
158   return gp_Pnt (RealLast(), RealLast(), RealLast());
159 }
160
161 //=======================================================================
162 // function : MarkDirty
163 // purpose  : Marks BVH tree of the set as outdated. It will be rebuild
164 //            at the next call of BVH()
165 //=======================================================================
166 void Select3D_SensitiveSet::MarkDirty()
167 {
168   myContent->MarkDirty();
169 }
170
171 //=======================================================================
172 // function : Clear
173 // purpose  : Destroys cross-reference to avoid memory leak
174 //=======================================================================
175 void Select3D_SensitiveSet::Clear()
176 {
177   myContent.Nullify();
178 }