0030480: Visualization - Clear of Select3D_SensitiveGroup does not update internal...
[occt.git] / src / Select3D / Select3D_SensitiveGroup.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 62792e8..9827b39
 // Created on: 1998-04-16
 // Created by: Robert COUBLANC
 // Copyright (c) 1998-1999 Matra Datavision
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
+#include <Select3D_SensitiveGroup.hxx>
 
-
-#include <Select3D_SensitiveGroup.ixx>
-#include <Select3D_ListIteratorOfListOfSensitive.hxx>
 #include <Precision.hxx>
 
+IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveGroup,Select3D_SensitiveSet)
+
 //=======================================================================
 //function : Creation
-//purpose  : 
+//purpose  :
 //=======================================================================
-Select3D_SensitiveGroup::Select3D_SensitiveGroup(const Handle(SelectBasics_EntityOwner)& OwnerId,
-                                                 const Standard_Boolean MatchAll):
-Select3D_SensitiveEntity(OwnerId),
-myMustMatchAll(MatchAll)
-{
-}
+Select3D_SensitiveGroup::Select3D_SensitiveGroup (const Handle(SelectBasics_EntityOwner)& theOwnerId,
+                                                  const Standard_Boolean theIsMustMatchAll)
+: Select3D_SensitiveSet (theOwnerId),
+  myMustMatchAll (theIsMustMatchAll),
+  myToCheckOverlapAll (Standard_False),
+  myCenter (0.0, 0.0, 0.0) {}
 
 //=======================================================================
 //function : Creation
-//purpose  : 
-//=======================================================================
-
-Select3D_SensitiveGroup::Select3D_SensitiveGroup(const Handle(SelectBasics_EntityOwner)& OwnerId,
-                                                 Select3D_ListOfSensitive& TheList, 
-                                                 const Standard_Boolean MatchAll):
-Select3D_SensitiveEntity(OwnerId),
-myMustMatchAll(MatchAll)
+//purpose  :
+//=======================================================================
+Select3D_SensitiveGroup::Select3D_SensitiveGroup (const Handle(SelectBasics_EntityOwner)& theOwnerId,
+                                                  Select3D_EntitySequence& theEntities,
+                                                  const Standard_Boolean theIsMustMatchAll)
+: Select3D_SensitiveSet (theOwnerId),
+  myEntities (Max (1, theEntities.Size())),
+  myMustMatchAll (theIsMustMatchAll),
+  myToCheckOverlapAll (Standard_False),
+  myCenter (0.0, 0.0, 0.0)
 {
-  myList.Append(TheList);
+  for (Select3D_EntitySequenceIter anIter (theEntities); anIter.More(); anIter.Next())
+  {
+    const Handle(Select3D_SensitiveEntity)& anEntity = anIter.Value();
+    const Standard_Integer aPrevExtent = myEntities.Extent();
+    if (myEntities.Add (anEntity) <= aPrevExtent)
+    {
+      continue;
+    }
+
+    myBndBox.Combine (anEntity->BoundingBox());
+    myBVHPrimIndexes.Append (myEntities.Extent());
+    myCenter.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
+  }
+
+  myCenter.ChangeCoord().Divide (static_cast<Standard_Real> (myEntities.Extent()));
+
+  MarkDirty();
 }
 
 //=======================================================================
 //function : Add
-//purpose  : No control of  entities inside 
+//purpose  : No control of entities inside
 //=======================================================================
+void Select3D_SensitiveGroup::Add (Select3D_EntitySequence& theEntities)
+{
+  if (theEntities.IsEmpty())
+  {
+    return;
+  }
 
-void Select3D_SensitiveGroup::Add(Select3D_ListOfSensitive& LL) 
-{myList.Append(LL);}
+  gp_Pnt aCent (0.0, 0.0, 0.0);
+  myEntities.ReSize (myEntities.Extent() + theEntities.Size());
+  for (Select3D_EntitySequenceIter anIter (theEntities); anIter.More(); anIter.Next())
+  {
+    const Handle(Select3D_SensitiveEntity)& anEntity = anIter.Value();
+    const Standard_Integer aPrevExtent = myEntities.Extent();
+    if (myEntities.Add (anEntity) <= aPrevExtent)
+    {
+      continue;
+    }
+
+    myBndBox.Combine (anEntity->BoundingBox());
+    myBVHPrimIndexes.Append (myEntities.Extent());
+    aCent.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
+  }
+  aCent.ChangeCoord().Divide (myEntities.Extent());
+  myCenter = (myCenter.XYZ() + aCent.XYZ()).Multiplied (0.5);
+}
 
 //=======================================================================
 //function : Add
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-void Select3D_SensitiveGroup::Add(const Handle(Select3D_SensitiveEntity)& aSensitive) 
+void Select3D_SensitiveGroup::Add (const Handle(Select3D_SensitiveEntity)& theSensitive)
 {
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next())
+  const Standard_Integer aPrevExtent = myEntities.Extent();
+  if (myEntities.Add (theSensitive) <= aPrevExtent)
+  {
+    return;
+  }
+
+  myBVHPrimIndexes.Append (myEntities.Extent());
+  myBndBox.Combine (theSensitive->BoundingBox());
+  myCenter.ChangeCoord() += theSensitive->CenterOfGeometry().XYZ();
+  if (myEntities.Extent() >= 2)
   {
-    if(It.Value()==aSensitive) return;
+    myCenter.ChangeCoord().Multiply (0.5);
   }
-  myList.Append(aSensitive);
 }
 
 //=======================================================================
 //function : Remove
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-void Select3D_SensitiveGroup::Remove(const Handle(Select3D_SensitiveEntity)& aSensitive) 
+void Select3D_SensitiveGroup::Remove (const Handle(Select3D_SensitiveEntity)& theSensitive)
 {
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next())
+  if (!myEntities.RemoveKey (theSensitive))
   {
-    if(It.Value()==aSensitive)
-    {
-      myList.Remove(It);
-      return;
-    }
+    return;
+  }
+
+  myBndBox.Clear();
+  myCenter = gp_Pnt (0.0, 0.0, 0.0);
+  myBVHPrimIndexes.Clear();
+  for (Standard_Integer anIdx = 1; anIdx <= myEntities.Size(); ++anIdx)
+  {
+    const Handle(Select3D_SensitiveEntity)& anEntity = myEntities.FindKey (anIdx);
+    myBndBox.Combine (anEntity->BoundingBox());
+    myCenter.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
+    myBVHPrimIndexes.Append (anIdx);
   }
+  myCenter.ChangeCoord().Divide (static_cast<Standard_Real> (myEntities.Extent()));
 }
 
 //=======================================================================
 //function : IsIn
-//purpose  : 
+//purpose  :
 //=======================================================================
-
-Standard_Boolean Select3D_SensitiveGroup::IsIn(const Handle(Select3D_SensitiveEntity)& aSensitive) const
+Standard_Boolean Select3D_SensitiveGroup::IsIn (const Handle(Select3D_SensitiveEntity)& theSensitive) const
 {
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next())
-  {
-    if(It.Value()==aSensitive)
-      return Standard_True;
-  }
-  return Standard_False;
+  return myEntities.Contains (theSensitive);
 }
 
 //=======================================================================
 //function : Clear
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void Select3D_SensitiveGroup::Clear()
-{myList.Clear();}
-
-//=======================================================================
-//function : Project
-//purpose  : 
-//=======================================================================
-
-void Select3D_SensitiveGroup::Project(const Handle(Select3D_Projector)& aProjector) 
 {
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next()) 
-  {
-    It.Value()->Project(aProjector);
-  }
+  myEntities.Clear();
+  myBndBox.Clear();
+  myCenter = gp_Pnt (0.0, 0.0, 0.0);
+  myBVHPrimIndexes.Clear();
 }
 
 //=======================================================================
-//function : Areas
-//purpose  : 
+// function : NbSubElements
+// purpose  : Returns the amount of sub-entities
 //=======================================================================
-
-void Select3D_SensitiveGroup::Areas(SelectBasics_ListOfBox2d& boxes) 
+Standard_Integer Select3D_SensitiveGroup::NbSubElements()
 {
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next()) 
-  {
-    It.Value()->Areas(boxes);
-  }
+  return myEntities.Size();
 }
 
 //=======================================================================
 //function : GetConnected
-//purpose  : 
+//purpose  :
 //=======================================================================
 
-Handle(Select3D_SensitiveEntity) Select3D_SensitiveGroup::GetConnected(const TopLoc_Location& aLocation) 
+Handle(Select3D_SensitiveEntity) Select3D_SensitiveGroup::GetConnected()
 {
-  Handle(Select3D_SensitiveGroup) newgroup = new Select3D_SensitiveGroup(myOwnerId,myMustMatchAll);
-  Select3D_ListOfSensitive LL;
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next()) 
+  Handle(Select3D_SensitiveGroup) aNewEntity = new Select3D_SensitiveGroup (myOwnerId, myMustMatchAll);
+  Select3D_EntitySequence aConnectedEnt;
+  for (Select3D_IndexedMapOfEntity::Iterator anEntityIter (myEntities); anEntityIter.More(); anEntityIter.Next())
   {
-    LL.Append(It.Value()->GetConnected(aLocation));
+    aConnectedEnt.Append (anEntityIter.Value()->GetConnected());
   }
-  newgroup->Add(LL);
-  return newgroup;
+  aNewEntity->Add (aConnectedEnt);
+  return aNewEntity;
 }
 
 //=======================================================================
-//function : SetLocation
-//purpose  : 
+//function : Matches
+//purpose  :
 //=======================================================================
-
-void Select3D_SensitiveGroup::SetLocation(const TopLoc_Location& aLoc) 
+Standard_Boolean Select3D_SensitiveGroup::Matches (SelectBasics_SelectingVolumeManager& theMgr,
+                                                   SelectBasics_PickResult& thePickResult)
 {
-  if(aLoc.IsIdentity()) return;
-
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next())
+  const Standard_Boolean toMatchAll = theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point
+                                   && myMustMatchAll;
+  const Standard_Boolean toCheckAll = theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point
+                                   && myToCheckOverlapAll;
+  if (!toMatchAll && !toCheckAll)
   {
-    It.Value()->SetLocation(aLoc);
+    return Select3D_SensitiveSet::Matches (theMgr, thePickResult);
   }
 
-  if(HasLocation())
-    if(aLoc == Location()) return;
-  
-  Select3D_SensitiveEntity::SetLocation(aLoc);
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next()) 
+  SelectBasics_PickResult aPickResult;
+  Standard_Boolean isFailed = Standard_False;
+  for (Select3D_IndexedMapOfEntity::Iterator anEntityIter (myEntities); anEntityIter.More(); anEntityIter.Next())
   {
-    if(It.Value()->HasLocation())
+    const Handle(Select3D_SensitiveEntity)& aChild = anEntityIter.Value();
+    if (!aChild->Matches (theMgr, aPickResult))
     {
-      if(It.Value()->Location()!=aLoc) 
-        It.Value()->SetLocation(It.Value()->Location()*aLoc);
+      if (toMatchAll)
+      {
+        isFailed = Standard_True;
+        if (!toCheckAll)
+        {
+          break;
+        }
+      }
     }
     else
-      It.Value()->SetLocation(aLoc);
+    {
+      thePickResult = SelectBasics_PickResult::Min (thePickResult, aPickResult);
+    }
+  }
+  if (isFailed)
+  {
+    return Standard_False;
   }
+
+  thePickResult.SetDistToGeomCenter(distanceToCOG(theMgr));
+  return Standard_True;
 }
 
 //=======================================================================
-//function : ResetLocation
-//purpose  : 
+//function : Set
+//purpose  :
 //=======================================================================
-
-void Select3D_SensitiveGroup::ResetLocation() 
-{
- if(!HasLocation()) return;
- for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next())
- {
-   if(It.Value()->HasLocation() && It.Value()->Location()!=Location())
-     It.Value()->SetLocation(It.Value()->Location()*Location().Inverted());
-   else
-     It.Value()->ResetLocation();
- }
- Select3D_SensitiveEntity::ResetLocation();
+void Select3D_SensitiveGroup::Set (const Handle(SelectBasics_EntityOwner)& theOwnerId)
+{ 
+  Select3D_SensitiveEntity::Set (theOwnerId);
+  for (Select3D_IndexedMapOfEntity::Iterator anEntityIter (myEntities); anEntityIter.More(); anEntityIter.Next())
+  {
+    anEntityIter.Value()->Set (theOwnerId);
+  }
 }
 
 //=======================================================================
-//function : Matches
-//purpose  : 
+// function : BoundingBox
+// purpose  : Returns bounding box of the group. If location
+//            transformation is set, it will be applied
 //=======================================================================
-
-Standard_Boolean Select3D_SensitiveGroup::Matches (const SelectBasics_PickArgs& thePickArgs,
-                                                   Standard_Real& theMatchDMin,
-                                                   Standard_Real& theMatchDepth)
+Select3D_BndBox3d Select3D_SensitiveGroup::BoundingBox()
 {
-  theMatchDMin = RealLast();
-  theMatchDepth = RealLast();
-  Standard_Real aChildDMin, aChildDepth;
-  Standard_Boolean isMatched = Standard_False;
+  if (myBndBox.IsValid())
+    return myBndBox;
 
-  Select3D_ListIteratorOfListOfSensitive anIt (myList);
-  for (; anIt.More(); anIt.Next())
+  // do not apply the transformation because sensitives AABBs
+  // are already transformed
+  for (Select3D_IndexedMapOfEntity::Iterator anEntityIter (myEntities); anEntityIter.More(); anEntityIter.Next())
   {
-    Handle(SelectBasics_SensitiveEntity)& aChild = anIt.Value();
-    if (!aChild->Matches (thePickArgs, aChildDMin, aChildDepth))
-    {
-      continue;
-    }
+    myBndBox.Combine (anEntityIter.Value()->BoundingBox());
+  }
 
-    if (!isMatched)
-    {
-      theMatchDMin = aChildDMin;
-      isMatched = Standard_True;
-    }
+  return myBndBox;
+}
 
-    theMatchDepth = Min (aChildDepth, theMatchDepth);
-  }
+//=======================================================================
+// function : CenterOfGeometry
+// purpose  : Returns center of group. If location transformation
+//            is set, it will be applied
+//=======================================================================
+gp_Pnt Select3D_SensitiveGroup::CenterOfGeometry() const
+{
+  return myCenter;
+}
 
-  return isMatched;
+//=======================================================================
+// function : Box
+// purpose  : Returns bounding box of sensitive entity with index theIdx
+//=======================================================================
+Select3D_BndBox3d Select3D_SensitiveGroup::Box (const Standard_Integer theIdx) const
+{
+  const Standard_Integer anElemIdx = myBVHPrimIndexes.Value (theIdx);
+  return myEntities.FindKey (anElemIdx)->BoundingBox();
 }
 
 //=======================================================================
-//function : Matches
-//purpose  :  si on doit tout matcher, on ne repond oui que si toutes
-//            les primitives repondent oui
-//=======================================================================
-Standard_Boolean Select3D_SensitiveGroup::Matches(const Standard_Real XMin, 
-                                                  const Standard_Real YMin, 
-                                                  const Standard_Real XMax, 
-                                                  const Standard_Real YMax, 
-                                                  const Standard_Real aTol) 
+// function : Center
+// purpose  : Returns geometry center of sensitive entity with index
+//            theIdx in the vector along the given axis theAxis
+//=======================================================================
+Standard_Real Select3D_SensitiveGroup::Center (const Standard_Integer theIdx,
+                                               const Standard_Integer theAxis) const
 {
-  Standard_Boolean result(Standard_True);
-  
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next())
-  {
-    if(It.Value()->Matches(XMin,YMin,XMax,YMax,aTol))
-    {
-      if(!myMustMatchAll)
-        return Standard_True;
-    }
-    // ca ne matches pas..
-    else 
-    {
-      if(myMustMatchAll) 
-        return Standard_False;
-      else 
-        result = Standard_False;
-    }
-  }
-  return result;
+  const Standard_Integer anElemIdx = myBVHPrimIndexes.Value (theIdx);
+  const gp_Pnt aCenter = myEntities.FindKey (anElemIdx)->CenterOfGeometry();
+  return theAxis == 0 ? aCenter.X() : (theAxis == 1 ? aCenter.Y() : aCenter.Z());
 }
 
 //=======================================================================
-//function : Matches
-//purpose  : 
+// function : Swap
+// purpose  : Swaps items with indexes theIdx1 and theIdx2 in the vector
 //=======================================================================
+void Select3D_SensitiveGroup::Swap (const Standard_Integer theIdx1,
+                                    const Standard_Integer theIdx2)
+{
+  const Standard_Integer anEntIdx1 = myBVHPrimIndexes.Value (theIdx1);
+  const Standard_Integer anEntIdx2 = myBVHPrimIndexes.Value (theIdx2);
 
-Standard_Boolean Select3D_SensitiveGroup::
-Matches (const TColgp_Array1OfPnt2d& aPoly,
-         const Bnd_Box2d& aBox,
-         const Standard_Real aTol)
-{ 
-  Standard_Boolean result(Standard_True);
-  
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next())
-  {
-    if(It.Value()->Matches(aPoly, aBox, aTol))
-    {
-      if(!myMustMatchAll) 
-        return Standard_True;
-    }
-    else 
-    {
-      if(myMustMatchAll) 
-        return Standard_False;
-      else 
-        result = Standard_False;
-    }
-  }
-  return result;
+  myBVHPrimIndexes.ChangeValue (theIdx1) = anEntIdx2;
+  myBVHPrimIndexes.ChangeValue (theIdx2) = anEntIdx1;
 }
 
 //=======================================================================
-//function : MaxBoxes
-//purpose  : 
+// function : Size
+// purpose  : Returns the length of vector of sensitive entities
 //=======================================================================
+Standard_Integer Select3D_SensitiveGroup::Size() const
+{
+  return myBVHPrimIndexes.Size();
+}
 
-Standard_Integer Select3D_SensitiveGroup::MaxBoxes() const
+// =======================================================================
+// function : overlapsElement
+// purpose  : Checks whether the entity with index theIdx overlaps the
+//            current selecting volume
+// =======================================================================
+Standard_Boolean Select3D_SensitiveGroup::overlapsElement (SelectBasics_PickResult& thePickResult,
+                                                           SelectBasics_SelectingVolumeManager& theMgr,
+                                                           Standard_Integer theElemIdx,
+                                                           Standard_Boolean )
 {
-  Standard_Integer nbboxes(0);
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next()){
-    nbboxes+=It.Value()->MaxBoxes();
+  const Standard_Integer aSensitiveIdx = myBVHPrimIndexes.Value (theElemIdx);
+  if (myEntities.FindKey (aSensitiveIdx)->Matches (theMgr, thePickResult))
+  {
+    return Standard_True;
   }
-  return nbboxes;
+
+  return Standard_False;
 }
 
-//=======================================================================
-//function : Set
-//purpose  : 
-//=======================================================================
+// =======================================================================
+// function : elementIsInside
+// purpose  :
+// =======================================================================
+Standard_Boolean Select3D_SensitiveGroup::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
+                                                           Standard_Integer theElemIdx,
+                                                           Standard_Boolean theIsFullInside)
+{
+  SelectBasics_PickResult aDummy;
+  return overlapsElement (aDummy, theMgr, theElemIdx, theIsFullInside);
+}
 
-void Select3D_SensitiveGroup::Set 
-  (const Handle(SelectBasics_EntityOwner)& TheOwnerId)
-{ 
-  Select3D_SensitiveEntity::Set(TheOwnerId);
-  // set TheOwnerId for each element of sensitive group
-  for(Select3D_ListIteratorOfListOfSensitive It(myList);It.More();It.Next())
-    It.Value()->Set(TheOwnerId);
+// =======================================================================
+// function : distanceToCOG
+// purpose  : Calculates distance from the 3d projection of used-picked
+//            screen point to center of the geometry
+// =======================================================================
+Standard_Real Select3D_SensitiveGroup::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
+{
+  return theMgr.DistToGeometryCenter (CenterOfGeometry());
 }