f751596e |
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> |
f751596e |
17 | |
85114087 |
18 | #include <BVH_LinearBuilder.hxx> |
f751596e |
19 | |
92efcf78 |
20 | IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveSet,Select3D_SensitiveEntity) |
21 | |
f5b72419 |
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 | |
f751596e |
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) |
85114087 |
51 | : Select3D_SensitiveEntity (theOwnerId), |
52 | myDetectedIdx (-1) |
f751596e |
53 | { |
85114087 |
54 | myContent.SetSensitiveSet (this); |
f5b72419 |
55 | myContent.SetBuilder (THE_SENS_SET_BUILDER); |
85114087 |
56 | myContent.MarkDirty(); |
f751596e |
57 | } |
58 | |
59 | //======================================================================= |
60 | // function : BVH |
61 | // purpose : Builds BVH tree for sensitive set |
62 | //======================================================================= |
63 | void Select3D_SensitiveSet::BVH() |
64 | { |
85114087 |
65 | myContent.GetBVH(); |
f751596e |
66 | } |
67 | |
4a056d20 |
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 | |
f751596e |
81 | //======================================================================= |
82 | // function : Matches |
4a056d20 |
83 | // purpose : |
f751596e |
84 | //======================================================================= |
4a056d20 |
85 | Standard_Boolean Select3D_SensitiveSet::matches (SelectBasics_SelectingVolumeManager& theMgr, |
86 | SelectBasics_PickResult& thePickResult, |
87 | Standard_Boolean theToCheckAllInside) |
f751596e |
88 | { |
a228288f |
89 | myDetectedIdx = -1; |
85114087 |
90 | const BVH_Tree<Standard_Real, 3, BVH_BinaryTree>* aBVH = myContent.GetBVH().get(); |
85114087 |
91 | if (myContent.Size() < 1 || !theMgr.Overlaps (aBVH->MinPoint (0), |
92 | aBVH->MaxPoint (0))) |
f751596e |
93 | { |
94 | return Standard_False; |
95 | } |
96 | |
4a056d20 |
97 | NodeInStack aStack[BVH_Constants_MaxTreeDepth]; |
98 | NodeInStack aNode; |
99 | |
f751596e |
100 | Standard_Integer aHead = -1; |
2157d6ac |
101 | |
f751596e |
102 | Standard_Integer aMatchesNb = -1; |
17017555 |
103 | SelectBasics_PickResult aPickResult; |
4a056d20 |
104 | const bool toCheckFullInside = (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point); |
f751596e |
105 | for (;;) |
106 | { |
4a056d20 |
107 | const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode.Id]; |
2157d6ac |
108 | |
109 | if (aData.x() == 0) // is inner node |
f751596e |
110 | { |
4a056d20 |
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 | } |
2157d6ac |
120 | |
4a056d20 |
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 | } |
2157d6ac |
127 | |
128 | if (!theMgr.IsOverlapAllowed()) // inclusion test |
f751596e |
129 | { |
4a056d20 |
130 | if (!theToCheckAllInside) |
2157d6ac |
131 | { |
4a056d20 |
132 | if (!toCheckLft || !toCheckRgh) |
133 | { |
134 | return Standard_False; // no inclusion |
135 | } |
2157d6ac |
136 | |
4a056d20 |
137 | // skip extra checks |
138 | toCheckLft &= !aLeft.IsFullInside; |
139 | toCheckRgh &= !aRight.IsFullInside; |
140 | } |
f751596e |
141 | } |
2157d6ac |
142 | |
143 | if (toCheckLft || toCheckRgh) |
f751596e |
144 | { |
4a056d20 |
145 | aNode = toCheckLft ? aLeft : aRight; |
2157d6ac |
146 | if (toCheckLft && toCheckRgh) |
147 | { |
4a056d20 |
148 | aStack[++aHead] = aRight; |
2157d6ac |
149 | } |
f751596e |
150 | } |
151 | else |
152 | { |
153 | if (aHead < 0) |
f751596e |
154 | break; |
f751596e |
155 | |
2157d6ac |
156 | aNode = aStack[aHead--]; |
f751596e |
157 | } |
158 | } |
159 | else |
160 | { |
2157d6ac |
161 | for (Standard_Integer anElemIdx = aData.y(); anElemIdx <= aData.z(); ++anElemIdx) |
f751596e |
162 | { |
2157d6ac |
163 | if (!theMgr.IsOverlapAllowed()) // inclusion test |
f751596e |
164 | { |
4a056d20 |
165 | if (!elementIsInside (theMgr, anElemIdx, aNode.IsFullInside)) |
f751596e |
166 | { |
4a056d20 |
167 | if (theToCheckAllInside) |
168 | { |
169 | continue; |
170 | } |
2157d6ac |
171 | return Standard_False; |
f751596e |
172 | } |
2157d6ac |
173 | } |
174 | else // overlap test |
175 | { |
4a056d20 |
176 | if (!overlapsElement (aPickResult, theMgr, anElemIdx, aNode.IsFullInside)) |
2157d6ac |
177 | { |
178 | continue; |
179 | } |
180 | |
17017555 |
181 | if (thePickResult.Depth() > aPickResult.Depth()) |
2157d6ac |
182 | { |
17017555 |
183 | thePickResult = aPickResult; |
2157d6ac |
184 | myDetectedIdx = anElemIdx; |
185 | } |
f751596e |
186 | } |
4a056d20 |
187 | ++aMatchesNb; |
f751596e |
188 | } |
2157d6ac |
189 | |
f751596e |
190 | if (aHead < 0) |
f751596e |
191 | break; |
f751596e |
192 | |
2157d6ac |
193 | aNode = aStack[aHead--]; |
f751596e |
194 | } |
195 | } |
196 | |
197 | if (aMatchesNb != -1) |
198 | { |
17017555 |
199 | thePickResult.SetDistToGeomCenter(distanceToCOG(theMgr)); |
f751596e |
200 | } |
201 | |
4a056d20 |
202 | return aMatchesNb != -1 |
203 | || (!theToCheckAllInside && !theMgr.IsOverlapAllowed()); |
f751596e |
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 | |
f751596e |
227 | //======================================================================= |
228 | // function : Clear |
229 | // purpose : Destroys cross-reference to avoid memory leak |
230 | //======================================================================= |
231 | void Select3D_SensitiveSet::Clear() |
232 | { |
85114087 |
233 | // |
2157d6ac |
234 | } |