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 <Precision.hxx>
18 #include <Select3D_SensitiveGroup.hxx>
19 #include <TopLoc_Location.hxx>
22 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveGroup,Select3D_SensitiveSet)
24 //=======================================================================
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) {}
34 //=======================================================================
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)
44 myCenter = gp_Pnt (0.0, 0.0, 0.0);
46 for (Select3D_EntitySequenceIter anIter (theEntities); anIter.More(); anIter.Next())
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();
55 myCenter.ChangeCoord().Divide (static_cast<Standard_Real> (myEntities.Size()));
60 //=======================================================================
62 //purpose : No control of entities inside
63 //=======================================================================
64 void Select3D_SensitiveGroup::Add (Select3D_EntitySequence& theEntities)
66 gp_Pnt aCent (0.0, 0.0, 0.0);
67 for (Select3D_EntitySequenceIter anIter (theEntities); anIter.More(); anIter.Next())
69 myEntities.Append (anIter.Value());
70 myBndBox.Combine (anIter.Value()->BoundingBox());
71 myBVHPrimIndexes.Append (myEntities.Size());
72 aCent.ChangeCoord() += anIter.Value()->CenterOfGeometry().XYZ();
74 aCent.ChangeCoord().Divide (myEntities.Length());
75 myCenter = (myCenter.XYZ() + aCent.XYZ()).Multiplied (0.5);
78 //=======================================================================
81 //=======================================================================
82 void Select3D_SensitiveGroup::Add (const Handle(Select3D_SensitiveEntity)& theSensitive)
84 for (Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
86 if (anIter.Value() == theSensitive)
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())
95 myCenter.ChangeCoord().Multiply (0.5);
99 //=======================================================================
102 //=======================================================================
103 void Select3D_SensitiveGroup::Remove (const Handle(Select3D_SensitiveEntity)& theSensitive)
105 Standard_Boolean isSensitiveRemoved = Standard_False;
106 for (Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
108 if (anIter.Value() == theSensitive)
110 myEntities.Remove (anIter);
111 isSensitiveRemoved = Standard_True;
116 if (isSensitiveRemoved)
119 myCenter = gp_Pnt (0.0, 0.0, 0.0);
120 myBVHPrimIndexes.Clear();
121 for (Standard_Integer anIdx = 1; anIdx <= myEntities.Size(); ++anIdx)
123 myBndBox.Combine (myEntities.Value (anIdx)->BoundingBox());
124 myCenter.ChangeCoord() += myEntities.Value (anIdx)->CenterOfGeometry().XYZ();
125 myBVHPrimIndexes.Append (anIdx);
127 myCenter.ChangeCoord().Divide (static_cast<Standard_Real> (myEntities.Size()));
131 //=======================================================================
134 //=======================================================================
135 Standard_Boolean Select3D_SensitiveGroup::IsIn (const Handle(Select3D_SensitiveEntity)& theSensitive) const
137 for(Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
139 if (anIter.Value() == theSensitive)
140 return Standard_True;
142 return Standard_False;
145 //=======================================================================
148 //=======================================================================
150 void Select3D_SensitiveGroup::Clear()
154 myCenter = gp_Pnt (0.0, 0.0, 0.0);
158 //=======================================================================
159 // function : NbSubElements
160 // purpose : Returns the amount of sub-entities
161 //=======================================================================
162 Standard_Integer Select3D_SensitiveGroup::NbSubElements()
164 return myEntities.Size();
167 //=======================================================================
168 //function : GetConnected
170 //=======================================================================
172 Handle(Select3D_SensitiveEntity) Select3D_SensitiveGroup::GetConnected()
174 Handle(Select3D_SensitiveGroup) aNewEntity = new Select3D_SensitiveGroup (myOwnerId, myMustMatchAll);
175 Select3D_EntitySequence aConnectedEnt;
176 for (Select3D_EntitySequenceIter It (myEntities); It.More(); It.Next())
178 aConnectedEnt.Append (It.Value()->GetConnected());
180 aNewEntity->Add (aConnectedEnt);
184 //=======================================================================
187 //=======================================================================
188 Standard_Boolean Select3D_SensitiveGroup::Matches (SelectBasics_SelectingVolumeManager& theMgr,
189 SelectBasics_PickResult& thePickResult)
192 || theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point)
193 return Select3D_SensitiveSet::Matches (theMgr, thePickResult);
195 Standard_Real aDepth = RealLast();
196 Standard_Real aDistToCOG = RealLast();
198 for (Select3D_EntitySequenceIter anIt (myEntities); anIt.More(); anIt.Next())
200 SelectBasics_PickResult aMatchResult;
201 Handle(SelectBasics_SensitiveEntity)& aChild = anIt.ChangeValue();
202 if (!aChild->Matches (theMgr, aMatchResult))
204 aMatchResult = SelectBasics_PickResult (RealLast(), RealLast());
205 return Standard_False;
208 aDepth = Min (aMatchResult.Depth(), aDepth);
211 aDistToCOG = theMgr.DistToGeometryCenter (CenterOfGeometry());
212 thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
214 return Standard_True;
217 //=======================================================================
220 //=======================================================================
221 void Select3D_SensitiveGroup::Set (const Handle(SelectBasics_EntityOwner)& theOwnerId)
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);
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()
236 if (myBndBox.IsValid())
239 // do not apply the transformation because sensitives AABBs
240 // are already transformed
241 for (Select3D_EntitySequenceIter anIter (myEntities); anIter.More(); anIter.Next())
243 myBndBox.Combine (anIter.Value()->BoundingBox());
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
259 //=======================================================================
261 // purpose : Returns bounding box of sensitive entity with index theIdx
262 //=======================================================================
263 Select3D_BndBox3d Select3D_SensitiveGroup::Box (const Standard_Integer theIdx) const
265 const Standard_Integer anElemIdx = myBVHPrimIndexes.Value (theIdx);
266 return myEntities.Value (anElemIdx)->BoundingBox();
269 //=======================================================================
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
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());
282 //=======================================================================
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)
289 const Standard_Integer anEntIdx1 = myBVHPrimIndexes.Value (theIdx1);
290 const Standard_Integer anEntIdx2 = myBVHPrimIndexes.Value (theIdx2);
292 myBVHPrimIndexes.ChangeValue (theIdx1) = anEntIdx2;
293 myBVHPrimIndexes.ChangeValue (theIdx2) = anEntIdx1;
296 //=======================================================================
298 // purpose : Returns the length of vector of sensitive entities
299 //=======================================================================
300 Standard_Integer Select3D_SensitiveGroup::Size() const
302 return myBVHPrimIndexes.Size();
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)
314 theMatchDepth = RealLast();
315 const Standard_Integer aSensitiveIdx = myBVHPrimIndexes.Value (theElemIdx);
316 SelectBasics_PickResult aResult;
317 if (myEntities.Value (aSensitiveIdx)->Matches (theMgr, aResult))
319 theMatchDepth = aResult.Depth();
320 return Standard_True;
323 return Standard_False;
326 // =======================================================================
327 // function : elementIsInside
329 // =======================================================================
330 Standard_Boolean Select3D_SensitiveGroup::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
331 const Standard_Integer theElemIdx)
333 Standard_Real aDummy;
334 return overlapsElement(theMgr, theElemIdx, aDummy);
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)
344 return theMgr.DistToGeometryCenter (CenterOfGeometry());