0026377: Passing Handle objects as arguments to functions as non-const reference...
[occt.git] / src / Select3D / Select3D_SensitiveGroup.cxx
1 // Created on: 1998-04-16
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Precision.hxx>
18 #include <Select3D_SensitiveGroup.hxx>
19 #include <TopLoc_Location.hxx>
20
21
22 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveGroup,Select3D_SensitiveSet)
23
24 //=======================================================================
25 //function : Creation
26 //purpose  :
27 //=======================================================================
28 Select3D_SensitiveGroup::Select3D_SensitiveGroup (const Handle(SelectBasics_EntityOwner)& theOwnerId,
29                                                   const Standard_Boolean theIsMustMatchAll)
30 : Select3D_SensitiveSet (theOwnerId),
31   myMustMatchAll (theIsMustMatchAll),
32   myCenter (0.0, 0.0, 0.0) {}
33
34 //=======================================================================
35 //function : Creation
36 //purpose  :
37 //=======================================================================
38 Select3D_SensitiveGroup::Select3D_SensitiveGroup (const Handle(SelectBasics_EntityOwner)& theOwnerId,
39                                                   Select3D_EntitySequence& theEntities,
40                                                   const Standard_Boolean theIsMustMatchAll)
41 : Select3D_SensitiveSet (theOwnerId),
42   myMustMatchAll (theIsMustMatchAll)
43 {
44   myCenter = gp_Pnt (0.0, 0.0, 0.0);
45
46   for (Select3D_EntitySequenceIter anIter (theEntities); anIter.More(); anIter.Next())
47   {
48     const Handle(Select3D_SensitiveEntity)& anEntity = anIter.Value();
49     myEntities.Append (anEntity);
50     myBndBox.Combine (anEntity->BoundingBox());
51     myBVHPrimIndexes.Append (myEntities.Size());
52     myCenter.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
53   }
54
55   myCenter.ChangeCoord().Divide (static_cast<Standard_Real> (myEntities.Size()));
56
57   MarkDirty();
58 }
59
60 //=======================================================================
61 //function : Add
62 //purpose  : No control of entities inside
63 //=======================================================================
64 void Select3D_SensitiveGroup::Add (Select3D_EntitySequence& theEntities)
65 {
66   gp_Pnt aCent (0.0, 0.0, 0.0);
67   for (Select3D_EntitySequenceIter anIter (theEntities); anIter.More(); anIter.Next())
68   {
69     myEntities.Append (anIter.Value());
70     myBndBox.Combine (anIter.Value()->BoundingBox());
71     myBVHPrimIndexes.Append (myEntities.Size());
72     aCent.ChangeCoord() += anIter.Value()->CenterOfGeometry().XYZ();
73   }
74   aCent.ChangeCoord().Divide (myEntities.Length());
75   myCenter = (myCenter.XYZ() + aCent.XYZ()).Multiplied (0.5);
76 }
77
78 //=======================================================================
79 //function : Add
80 //purpose  :
81 //=======================================================================
82 void Select3D_SensitiveGroup::Add (const Handle(Select3D_SensitiveEntity)& theSensitive)
83 {
84   for (Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
85   {
86     if (anIter.Value() == theSensitive)
87       return;
88   }
89   myEntities.Append (theSensitive);
90   myBVHPrimIndexes.Append (myEntities.Size());
91   myBndBox.Combine (theSensitive->BoundingBox());
92   myCenter.ChangeCoord() += theSensitive->CenterOfGeometry().XYZ();
93   if (myEntities.First() != myEntities.Last())
94   {
95     myCenter.ChangeCoord().Multiply (0.5);
96   }
97 }
98
99 //=======================================================================
100 //function : Remove
101 //purpose  :
102 //=======================================================================
103 void Select3D_SensitiveGroup::Remove (const Handle(Select3D_SensitiveEntity)& theSensitive)
104 {
105   Standard_Boolean isSensitiveRemoved = Standard_False;
106   for (Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
107   {
108     if (anIter.Value() == theSensitive)
109     {
110       myEntities.Remove (anIter);
111       isSensitiveRemoved = Standard_True;
112       break;
113     }
114   }
115
116   if (isSensitiveRemoved)
117   {
118     myBndBox.Clear();
119     myCenter = gp_Pnt (0.0, 0.0, 0.0);
120     myBVHPrimIndexes.Clear();
121     for (Standard_Integer anIdx = 1; anIdx <= myEntities.Size(); ++anIdx)
122     {
123       myBndBox.Combine (myEntities.Value (anIdx)->BoundingBox());
124       myCenter.ChangeCoord() += myEntities.Value (anIdx)->CenterOfGeometry().XYZ();
125       myBVHPrimIndexes.Append (anIdx);
126     }
127     myCenter.ChangeCoord().Divide (static_cast<Standard_Real> (myEntities.Size()));
128   }
129 }
130
131 //=======================================================================
132 //function : IsIn
133 //purpose  :
134 //=======================================================================
135 Standard_Boolean Select3D_SensitiveGroup::IsIn (const Handle(Select3D_SensitiveEntity)& theSensitive) const
136 {
137   for(Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
138   {
139     if (anIter.Value() == theSensitive)
140       return Standard_True;
141   }
142   return Standard_False;
143 }
144
145 //=======================================================================
146 //function : Clear
147 //purpose  :
148 //=======================================================================
149
150 void Select3D_SensitiveGroup::Clear()
151 {
152   myEntities.Clear();
153   myBndBox.Clear();
154   myCenter = gp_Pnt (0.0, 0.0, 0.0);
155   myEntities.Clear();
156 }
157
158 //=======================================================================
159 // function : NbSubElements
160 // purpose  : Returns the amount of sub-entities
161 //=======================================================================
162 Standard_Integer Select3D_SensitiveGroup::NbSubElements()
163 {
164   return myEntities.Size();
165 }
166
167 //=======================================================================
168 //function : GetConnected
169 //purpose  :
170 //=======================================================================
171
172 Handle(Select3D_SensitiveEntity) Select3D_SensitiveGroup::GetConnected()
173 {
174   Handle(Select3D_SensitiveGroup) aNewEntity = new Select3D_SensitiveGroup (myOwnerId, myMustMatchAll);
175   Select3D_EntitySequence aConnectedEnt;
176   for (Select3D_EntitySequenceIter It (myEntities); It.More(); It.Next()) 
177   {
178     aConnectedEnt.Append (It.Value()->GetConnected());
179   }
180   aNewEntity->Add (aConnectedEnt);
181   return aNewEntity;
182 }
183
184 //=======================================================================
185 //function : Matches
186 //purpose  :
187 //=======================================================================
188 Standard_Boolean Select3D_SensitiveGroup::Matches (SelectBasics_SelectingVolumeManager& theMgr,
189                                                    SelectBasics_PickResult& thePickResult)
190 {
191   if (!myMustMatchAll
192     || theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point)
193     return Select3D_SensitiveSet::Matches (theMgr, thePickResult);
194
195   Standard_Real aDepth     = RealLast();
196   Standard_Real aDistToCOG = RealLast();
197
198   for (Select3D_EntitySequenceIter anIt (myEntities); anIt.More(); anIt.Next())
199   {
200     SelectBasics_PickResult aMatchResult;
201     Handle(Select3D_SensitiveEntity)& aChild = anIt.ChangeValue();
202     if (!aChild->Matches (theMgr, aMatchResult))
203     {
204       aMatchResult = SelectBasics_PickResult (RealLast(), RealLast());
205       return Standard_False;
206     }
207
208     aDepth = Min (aMatchResult.Depth(), aDepth);
209   }
210
211   aDistToCOG = theMgr.DistToGeometryCenter (CenterOfGeometry());
212   thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
213
214   return Standard_True;
215 }
216
217 //=======================================================================
218 //function : Set
219 //purpose  :
220 //=======================================================================
221 void Select3D_SensitiveGroup::Set (const Handle(SelectBasics_EntityOwner)& theOwnerId)
222
223   Select3D_SensitiveEntity::Set (theOwnerId);
224   // set TheOwnerId for each element of sensitive group
225   for (Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
226     anIter.Value()->Set (theOwnerId);
227 }
228
229 //=======================================================================
230 // function : BoundingBox
231 // purpose  : Returns bounding box of the group. If location
232 //            transformation is set, it will be applied
233 //=======================================================================
234 Select3D_BndBox3d Select3D_SensitiveGroup::BoundingBox()
235 {
236   if (myBndBox.IsValid())
237     return myBndBox;
238
239   // do not apply the transformation because sensitives AABBs
240   // are already transformed
241   for (Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
242   {
243     myBndBox.Combine (anIter.Value()->BoundingBox());
244   }
245
246   return myBndBox;
247 }
248
249 //=======================================================================
250 // function : CenterOfGeometry
251 // purpose  : Returns center of group. If location transformation
252 //            is set, it will be applied
253 //=======================================================================
254 gp_Pnt Select3D_SensitiveGroup::CenterOfGeometry() const
255 {
256   return myCenter;
257 }
258
259 //=======================================================================
260 // function : Box
261 // purpose  : Returns bounding box of sensitive entity with index theIdx
262 //=======================================================================
263 Select3D_BndBox3d Select3D_SensitiveGroup::Box (const Standard_Integer theIdx) const
264 {
265   const Standard_Integer anElemIdx = myBVHPrimIndexes.Value (theIdx);
266   return myEntities.Value (anElemIdx)->BoundingBox();
267 }
268
269 //=======================================================================
270 // function : Center
271 // purpose  : Returns geometry center of sensitive entity with index
272 //            theIdx in the vector along the given axis theAxis
273 //=======================================================================
274 Standard_Real Select3D_SensitiveGroup::Center (const Standard_Integer theIdx,
275                                                const Standard_Integer theAxis) const
276 {
277   const Standard_Integer anElemIdx = myBVHPrimIndexes.Value (theIdx);
278   const gp_Pnt aCenter = myEntities.Value (anElemIdx)->CenterOfGeometry();
279   return theAxis == 0 ? aCenter.X() : (theAxis == 1 ? aCenter.Y() : aCenter.Z());
280 }
281
282 //=======================================================================
283 // function : Swap
284 // purpose  : Swaps items with indexes theIdx1 and theIdx2 in the vector
285 //=======================================================================
286 void Select3D_SensitiveGroup::Swap (const Standard_Integer theIdx1,
287                                     const Standard_Integer theIdx2)
288 {
289   const Standard_Integer anEntIdx1 = myBVHPrimIndexes.Value (theIdx1);
290   const Standard_Integer anEntIdx2 = myBVHPrimIndexes.Value (theIdx2);
291
292   myBVHPrimIndexes.ChangeValue (theIdx1) = anEntIdx2;
293   myBVHPrimIndexes.ChangeValue (theIdx2) = anEntIdx1;
294 }
295
296 //=======================================================================
297 // function : Size
298 // purpose  : Returns the length of vector of sensitive entities
299 //=======================================================================
300 Standard_Integer Select3D_SensitiveGroup::Size() const
301 {
302   return myBVHPrimIndexes.Size();
303 }
304
305 // =======================================================================
306 // function : overlapsElement
307 // purpose  : Checks whether the entity with index theIdx overlaps the
308 //            current selecting volume
309 // =======================================================================
310 Standard_Boolean Select3D_SensitiveGroup::overlapsElement (SelectBasics_SelectingVolumeManager& theMgr,
311                                                            Standard_Integer theElemIdx,
312                                                            Standard_Real& theMatchDepth)
313 {
314   theMatchDepth = RealLast();
315   const Standard_Integer aSensitiveIdx = myBVHPrimIndexes.Value (theElemIdx);
316   SelectBasics_PickResult aResult;
317   if (myEntities.Value (aSensitiveIdx)->Matches (theMgr, aResult))
318   {
319     theMatchDepth = aResult.Depth();
320     return Standard_True;
321   }
322
323   return Standard_False;
324 }
325
326 // =======================================================================
327 // function : elementIsInside
328 // purpose  :
329 // =======================================================================
330 Standard_Boolean Select3D_SensitiveGroup::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
331                                                            const Standard_Integer               theElemIdx)
332 {
333   Standard_Real aDummy;
334   return overlapsElement(theMgr, theElemIdx, aDummy);
335 }
336
337 // =======================================================================
338 // function : distanceToCOG
339 // purpose  : Calculates distance from the 3d projection of used-picked
340 //            screen point to center of the geometry
341 // =======================================================================
342 Standard_Real Select3D_SensitiveGroup::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
343 {
344   return theMgr.DistToGeometryCenter (CenterOfGeometry());
345 }