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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <Select3D_SensitiveGroup.hxx>
19 #include <Precision.hxx>
21 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveGroup,Select3D_SensitiveSet)
23 //=======================================================================
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) {}
33 //=======================================================================
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)
43 myCenter = gp_Pnt (0.0, 0.0, 0.0);
45 for (Select3D_EntitySequenceIter anIter (theEntities); anIter.More(); anIter.Next())
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();
54 myCenter.ChangeCoord().Divide (static_cast<Standard_Real> (myEntities.Size()));
59 //=======================================================================
61 //purpose : No control of entities inside
62 //=======================================================================
63 void Select3D_SensitiveGroup::Add (Select3D_EntitySequence& theEntities)
65 gp_Pnt aCent (0.0, 0.0, 0.0);
66 for (Select3D_EntitySequenceIter anIter (theEntities); anIter.More(); anIter.Next())
68 myEntities.Append (anIter.Value());
69 myBndBox.Combine (anIter.Value()->BoundingBox());
70 myBVHPrimIndexes.Append (myEntities.Size());
71 aCent.ChangeCoord() += anIter.Value()->CenterOfGeometry().XYZ();
73 aCent.ChangeCoord().Divide (myEntities.Length());
74 myCenter = (myCenter.XYZ() + aCent.XYZ()).Multiplied (0.5);
77 //=======================================================================
80 //=======================================================================
81 void Select3D_SensitiveGroup::Add (const Handle(Select3D_SensitiveEntity)& theSensitive)
83 for (Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
85 if (anIter.Value() == theSensitive)
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())
94 myCenter.ChangeCoord().Multiply (0.5);
98 //=======================================================================
101 //=======================================================================
102 void Select3D_SensitiveGroup::Remove (const Handle(Select3D_SensitiveEntity)& theSensitive)
104 Standard_Boolean isSensitiveRemoved = Standard_False;
105 for (Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
107 if (anIter.Value() == theSensitive)
109 myEntities.Remove (anIter);
110 isSensitiveRemoved = Standard_True;
115 if (isSensitiveRemoved)
118 myCenter = gp_Pnt (0.0, 0.0, 0.0);
119 myBVHPrimIndexes.Clear();
120 for (Standard_Integer anIdx = 1; anIdx <= myEntities.Size(); ++anIdx)
122 myBndBox.Combine (myEntities.Value (anIdx)->BoundingBox());
123 myCenter.ChangeCoord() += myEntities.Value (anIdx)->CenterOfGeometry().XYZ();
124 myBVHPrimIndexes.Append (anIdx);
126 myCenter.ChangeCoord().Divide (static_cast<Standard_Real> (myEntities.Size()));
130 //=======================================================================
133 //=======================================================================
134 Standard_Boolean Select3D_SensitiveGroup::IsIn (const Handle(Select3D_SensitiveEntity)& theSensitive) const
136 for(Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
138 if (anIter.Value() == theSensitive)
139 return Standard_True;
141 return Standard_False;
144 //=======================================================================
147 //=======================================================================
149 void Select3D_SensitiveGroup::Clear()
153 myCenter = gp_Pnt (0.0, 0.0, 0.0);
157 //=======================================================================
158 // function : NbSubElements
159 // purpose : Returns the amount of sub-entities
160 //=======================================================================
161 Standard_Integer Select3D_SensitiveGroup::NbSubElements()
163 return myEntities.Size();
166 //=======================================================================
167 //function : GetConnected
169 //=======================================================================
171 Handle(Select3D_SensitiveEntity) Select3D_SensitiveGroup::GetConnected()
173 Handle(Select3D_SensitiveGroup) aNewEntity = new Select3D_SensitiveGroup (myOwnerId, myMustMatchAll);
174 Select3D_EntitySequence aConnectedEnt;
175 for (Select3D_EntitySequenceIter It (myEntities); It.More(); It.Next())
177 aConnectedEnt.Append (It.Value()->GetConnected());
179 aNewEntity->Add (aConnectedEnt);
183 //=======================================================================
186 //=======================================================================
187 Standard_Boolean Select3D_SensitiveGroup::Matches (SelectBasics_SelectingVolumeManager& theMgr,
188 SelectBasics_PickResult& thePickResult)
191 || theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point)
192 return Select3D_SensitiveSet::Matches (theMgr, thePickResult);
194 Standard_Real aDepth = RealLast();
195 Standard_Real aDistToCOG = RealLast();
197 for (Select3D_EntitySequenceIter anIt (myEntities); anIt.More(); anIt.Next())
199 SelectBasics_PickResult aMatchResult;
200 Handle(Select3D_SensitiveEntity)& aChild = anIt.ChangeValue();
201 if (!aChild->Matches (theMgr, aMatchResult))
203 aMatchResult = SelectBasics_PickResult (RealLast(), RealLast());
204 return Standard_False;
207 aDepth = Min (aMatchResult.Depth(), aDepth);
210 aDistToCOG = theMgr.DistToGeometryCenter (CenterOfGeometry());
211 thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
213 return Standard_True;
216 //=======================================================================
219 //=======================================================================
220 void Select3D_SensitiveGroup::Set (const Handle(SelectBasics_EntityOwner)& theOwnerId)
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);
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()
235 if (myBndBox.IsValid())
238 // do not apply the transformation because sensitives AABBs
239 // are already transformed
240 for (Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
242 myBndBox.Combine (anIter.Value()->BoundingBox());
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
258 //=======================================================================
260 // purpose : Returns bounding box of sensitive entity with index theIdx
261 //=======================================================================
262 Select3D_BndBox3d Select3D_SensitiveGroup::Box (const Standard_Integer theIdx) const
264 const Standard_Integer anElemIdx = myBVHPrimIndexes.Value (theIdx);
265 return myEntities.Value (anElemIdx)->BoundingBox();
268 //=======================================================================
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
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());
281 //=======================================================================
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)
288 const Standard_Integer anEntIdx1 = myBVHPrimIndexes.Value (theIdx1);
289 const Standard_Integer anEntIdx2 = myBVHPrimIndexes.Value (theIdx2);
291 myBVHPrimIndexes.ChangeValue (theIdx1) = anEntIdx2;
292 myBVHPrimIndexes.ChangeValue (theIdx2) = anEntIdx1;
295 //=======================================================================
297 // purpose : Returns the length of vector of sensitive entities
298 //=======================================================================
299 Standard_Integer Select3D_SensitiveGroup::Size() const
301 return myBVHPrimIndexes.Size();
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)
313 theMatchDepth = RealLast();
314 const Standard_Integer aSensitiveIdx = myBVHPrimIndexes.Value (theElemIdx);
315 SelectBasics_PickResult aResult;
316 if (myEntities.Value (aSensitiveIdx)->Matches (theMgr, aResult))
318 theMatchDepth = aResult.Depth();
319 return Standard_True;
322 return Standard_False;
325 // =======================================================================
326 // function : elementIsInside
328 // =======================================================================
329 Standard_Boolean Select3D_SensitiveGroup::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
330 const Standard_Integer theElemIdx)
332 Standard_Real aDummy;
333 return overlapsElement(theMgr, theElemIdx, aDummy);
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)
343 return theMgr.DistToGeometryCenter (CenterOfGeometry());