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