0031313: Foundation Classes - Dump improvement for classes
[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(SelectMgr_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 namespace
69 {
70   //! This structure describes the node in BVH
71   struct NodeInStack
72   {
73     NodeInStack (Standard_Integer theId = 0,
74                  Standard_Boolean theIsFullInside = false) : Id (theId), IsFullInside (theIsFullInside) {}
75
76     Standard_Integer Id;           //!< node identifier
77     Standard_Boolean IsFullInside; //!< if the node is completely inside the current selection volume
78   };
79 }
80
81 //=======================================================================
82 // function : Matches
83 // purpose  :
84 //=======================================================================
85 Standard_Boolean Select3D_SensitiveSet::matches (SelectBasics_SelectingVolumeManager& theMgr,
86                                                  SelectBasics_PickResult& thePickResult,
87                                                  Standard_Boolean theToCheckAllInside)
88 {
89   myDetectedIdx = -1;
90   const BVH_Tree<Standard_Real, 3, BVH_BinaryTree>* aBVH = myContent.GetBVH().get();
91   if (myContent.Size() < 1 || !theMgr.Overlaps (aBVH->MinPoint (0),
92                                                 aBVH->MaxPoint (0)))
93   {
94     return Standard_False;
95   }
96
97   NodeInStack aStack[BVH_Constants_MaxTreeDepth];
98   NodeInStack aNode;
99
100   Standard_Integer aHead = -1;
101
102   Standard_Integer aMatchesNb = -1;
103   SelectBasics_PickResult aPickResult;
104   const bool toCheckFullInside = (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point);
105   for (;;)
106   {
107     const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode.Id];
108
109     if (aData.x() == 0) // is inner node
110     {
111       NodeInStack aLeft (aData.y(), toCheckFullInside), aRight(aData.z(), toCheckFullInside);
112       Standard_Boolean toCheckLft = Standard_True, toCheckRgh = Standard_True;
113       if (!aNode.IsFullInside)
114       {
115         toCheckLft = theMgr.Overlaps (aBVH->MinPoint (aLeft.Id), aBVH->MaxPoint (aLeft.Id), toCheckFullInside ? &aLeft.IsFullInside : NULL);
116         if (!toCheckLft)
117         {
118           aLeft.IsFullInside = Standard_False;
119         }
120
121         toCheckRgh = theMgr.Overlaps (aBVH->MinPoint (aRight.Id), aBVH->MaxPoint (aRight.Id), toCheckFullInside ? &aRight.IsFullInside : NULL);
122         if (!toCheckRgh)
123         {
124           aRight.IsFullInside = Standard_False;
125         }
126       }
127
128       if (!theMgr.IsOverlapAllowed()) // inclusion test
129       {
130         if (!theToCheckAllInside)
131         {
132           if (!toCheckLft || !toCheckRgh)
133           {
134             return Standard_False; // no inclusion
135           }
136
137           // skip extra checks
138           toCheckLft &= !aLeft.IsFullInside;
139           toCheckRgh &= !aRight.IsFullInside;
140         }
141       }
142
143       if (toCheckLft || toCheckRgh)
144       {
145         aNode = toCheckLft ? aLeft : aRight;
146         if (toCheckLft && toCheckRgh)
147         {
148           aStack[++aHead] = aRight;
149         }
150       }
151       else
152       {
153         if (aHead < 0)
154           break;
155
156         aNode = aStack[aHead--];
157       }
158     }
159     else
160     {
161       for (Standard_Integer anElemIdx = aData.y(); anElemIdx <= aData.z(); ++anElemIdx)
162       {
163         if (!theMgr.IsOverlapAllowed()) // inclusion test
164         {
165           if (!elementIsInside (theMgr, anElemIdx, aNode.IsFullInside))
166           {
167             if (theToCheckAllInside)
168             {
169               continue;
170             }
171             return Standard_False;
172           }
173         }
174         else // overlap test
175         {
176           if (!overlapsElement (aPickResult, theMgr, anElemIdx, aNode.IsFullInside))
177           {
178             continue;
179           }
180
181           if (thePickResult.Depth() > aPickResult.Depth())
182           {
183             thePickResult = aPickResult;
184             myDetectedIdx = anElemIdx;
185           }
186         }
187         ++aMatchesNb;
188       }
189
190       if (aHead < 0)
191         break;
192
193       aNode = aStack[aHead--];
194     }
195   }
196
197   if (aMatchesNb != -1)
198   {
199     thePickResult.SetDistToGeomCenter(distanceToCOG(theMgr));
200   }
201
202   return aMatchesNb != -1
203      || (!theToCheckAllInside && !theMgr.IsOverlapAllowed());
204 }
205
206 //=======================================================================
207 // function : BoundingBox
208 // purpose  : This method should be redefined in Select3D_SensitiveSet
209 //            descendants
210 //=======================================================================
211 Select3D_BndBox3d Select3D_SensitiveSet::BoundingBox()
212 {
213   return Select3D_BndBox3d (SelectMgr_Vec3 (RealLast()),
214                             SelectMgr_Vec3 (RealFirst()));
215 }
216
217 //=======================================================================
218 // function : CenterOfGeometry
219 // purpose  : This method should be redefined in Select3D_SensitiveSet
220 //            descendants
221 //=======================================================================
222 gp_Pnt Select3D_SensitiveSet::CenterOfGeometry() const
223 {
224   return gp_Pnt (RealLast(), RealLast(), RealLast());
225 }
226
227 //=======================================================================
228 // function : Clear
229 // purpose  : Destroys cross-reference to avoid memory leak
230 //=======================================================================
231 void Select3D_SensitiveSet::Clear()
232 {
233   //
234 }
235
236 //=======================================================================
237 //function : DumpJson
238 //purpose  :
239 //=======================================================================
240 void Select3D_SensitiveSet::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
241 {
242   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
243   OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Select3D_SensitiveEntity)
244
245   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myContent)
246
247   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDetectedIdx)
248
249   Select3D_BndBox3d aBoundingBox = ((Select3D_SensitiveSet*)this)->BoundingBox();
250   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &aBoundingBox)
251 }