0027732: Visualization - AIS_ConnectedInteractive crashes on NULL handle returned...
[occt.git] / src / AIS / AIS_ConnectedInteractive.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 71e3280..6a655f6
@@ -1,20 +1,45 @@
-// File:       AIS_ConnectedInteractive.cxx
-// Created:    Wed Jan  8 15:24:35 1997
-// Author:     Robert COUBLANC
-//             <rob@robox.paris1.matra-dtv.fr>
+// Created on: 1997-01-08
+// Created by: Robert COUBLANC
+// Copyright (c) 1997-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// 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.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
+#include <AIS_ConnectedInteractive.hxx>
 
-#include <Standard_NotImplemented.hxx>
-
-#include <AIS_ConnectedInteractive.ixx>
-#include <SelectMgr_EntityOwner.hxx>
-#include <Select3D_SensitiveEntity.hxx>
-#include <Geom_Transformation.hxx>
-
+#include <AIS_InteractiveContext.hxx>
+#include <AIS_Shape.hxx>
+#include <BRepTools.hxx>
+#include <NCollection_DataMap.hxx>
+#include <Precision.hxx>
+#include <Prs3d_Drawer.hxx>
+#include <Prs3d_Projector.hxx>
 #include <PrsMgr_ModedPresentation.hxx>
-#include <PrsMgr_Presentation3d.hxx>
-#include <OSD_Timer.hxx>
+#include <Select3D_SensitiveEntity.hxx>
+#include <SelectMgr_EntityOwner.hxx>
+#include <SelectMgr_Selection.hxx>
+#include <Standard_NotImplemented.hxx>
+#include <Standard_ProgramError.hxx>
+#include <Standard_Type.hxx>
+#include <StdPrs_HLRPolyShape.hxx>
+#include <StdPrs_WFShape.hxx>
+#include <StdSelect.hxx>
+#include <StdSelect_BRepOwner.hxx>
+#include <TopAbs_ShapeEnum.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_OrientedShapeMapHasher.hxx>
 
+IMPLEMENT_STANDARD_RTTIEXT(AIS_ConnectedInteractive,AIS_InteractiveObject)
 
 //=======================================================================
 //function : AIS_ConnectedInteractive
 //=======================================================================
 AIS_ConnectedInteractive::AIS_ConnectedInteractive(const PrsMgr_TypeOfPresentation3d aTypeOfPresentation3d):
 AIS_InteractiveObject(aTypeOfPresentation3d)
-{    
-  SetHilightMode(0);
-}
-
-//=======================================================================
-//function : Type
-//purpose  : 
-//=======================================================================
-AIS_KindOfInteractive AIS_ConnectedInteractive::Type() const
-{return AIS_KOI_Object;}
-
-Standard_Integer AIS_ConnectedInteractive::Signature() const
-{return 0; }
-
-
-
-
-//=======================================================================
-//function : Connect
-//purpose  : 
-//=======================================================================
-void AIS_ConnectedInteractive::
-Connect(const Handle(AIS_InteractiveObject)& anotherIObj)
 {
-  // To have the time to Disconnect below, 
-  // the old is kept for a while. 
-  if(myReference==anotherIObj) return;
-  myOldReference = myReference;
-//Disconnect();
-  myReference = anotherIObj ;
+  //
 }
 
 //=======================================================================
-//function : Connect
-//purpose  : 
+//function : connect
+//purpose  :
 //=======================================================================
-void AIS_ConnectedInteractive::
-Connect(const Handle(AIS_InteractiveObject)& anotherIobj, 
-       const TopLoc_Location& aLocation)
+void AIS_ConnectedInteractive::connect (const Handle(AIS_InteractiveObject)& theAnotherObj,
+                                        const Handle(Geom_Transformation)&   theLocation)
 {
-  if(myLocation!=aLocation)
-    myLocation = aLocation;
-  if(myReference!=anotherIobj) {
-    myOldReference = myReference; // necessary to disconnect below..
-//  Disconnect();
-    myReference = anotherIobj;}
-  
-}
+  if (myReference == theAnotherObj)
+  {
+    setLocalTransformation (theLocation);
+    return;
+  }
 
+  Handle(AIS_ConnectedInteractive) aConnected = Handle(AIS_ConnectedInteractive)::DownCast (theAnotherObj);
+  if (!aConnected.IsNull())
+  {
+    myReference = aConnected->myReference;
+  }
+  else if (theAnotherObj->HasOwnPresentations())
+  {
+    myReference = theAnotherObj;
+  }
+  else
+  {
+    throw Standard_ProgramError("AIS_ConnectedInteractive::Connect() - object without own presentation can not be connected");
+  }
+
+  if (!myReference.IsNull())
+  {
+    myTypeOfPresentation3d = myReference->TypeOfPresentation3d();
+  }
+  setLocalTransformation (theLocation);
+}
 
 //=======================================================================
 //function : Disconnect
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void AIS_ConnectedInteractive::Disconnect()
 {
-  for(Standard_Integer i =1;i<=myPresentations.Length();i++)
+  for(Standard_Integer aPrsIter = 1; aPrsIter <= myPresentations.Length(); ++aPrsIter)
+  {
+    const Handle(PrsMgr_Presentation)& aPrs = myPresentations (aPrsIter).Presentation();
+    if (!aPrs.IsNull())
     {
-      Handle(PrsMgr_Presentation3d) P = Handle(PrsMgr_Presentation3d)::DownCast(myPresentations(i).Presentation());
-      if(!P.IsNull()) {
-       P->Presentation()->DisconnectAll(Graphic3d_TOC_DESCENDANT);
-      }
+      aPrs->Presentation()->DisconnectAll (Graphic3d_TOC_DESCENDANT);
     }
+  }
 }
 //=======================================================================
 //function : Compute
-//purpose  : 
+//purpose  :
 //=======================================================================
+void AIS_ConnectedInteractive::Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+                                        const Handle(Prs3d_Presentation)&           thePrs,
+                                        const Standard_Integer                      theMode)
+{
+  if (HasConnection())
+  {
+    thePrs->Clear (Standard_False);
+    thePrs->RemoveAll();
 
-void AIS_ConnectedInteractive::
-Compute(const Handle(PrsMgr_PresentationManager3d)& aPresentationManager,
-       const Handle(Prs3d_Presentation)& aPresentation, 
-       const Standard_Integer aMode)
+    if (!myReference->HasInteractiveContext())
+    {
+      myReference->SetContext (GetContext());
+    }
+    thePrsMgr->Connect (this, myReference, theMode, theMode);
+    if (thePrsMgr->Presentation (myReference, theMode)->MustBeUpdated())
+    {
+      thePrsMgr->Update (myReference, theMode);
+    }
+  }
+
+  if (!thePrs.IsNull())
+  {
+    thePrs->ReCompute();
+  }
+}
+
+//=======================================================================
+//function : Compute
+//purpose  :
+//=======================================================================
+void AIS_ConnectedInteractive::Compute (const Handle(Prs3d_Projector)& theProjector,
+                                        const Handle(Geom_Transformation)& theTransformation,
+                                        const Handle(Prs3d_Presentation)& thePresentation)
 {
-  static Handle(Geom_Transformation) myPrsTrans ;
-
-  if(!(HasLocation() ||HasConnection())) return;
-  
-  if(HasConnection()){
-    aPresentation->Clear(Standard_False);
-    aPresentation->RemoveAll();
-    aPresentationManager->Connect( this,myReference, aMode, aMode);
-    if(aPresentationManager->Presentation(myReference,aMode)->MustBeUpdated())
-      aPresentationManager->Update(myReference,aMode);
-    
-  }
-  if(HasLocation()){
-    myPrsTrans = new Geom_Transformation(myLocation.Transformation());
-    aPresentationManager->Transform(this, myPrsTrans, aMode);  }
-  aPresentation->ReCompute();
+  updateShape (Standard_False);
+  if (myShape.IsNull())
+  {
+    return;
+  }
+  const TopLoc_Location& aLocation = myShape.Location();
+  TopoDS_Shape aShape = myShape.Located (TopLoc_Location (theTransformation->Trsf()) * aLocation);
+  Compute (theProjector, thePresentation, aShape);
 }
 
-void AIS_ConnectedInteractive::Compute(const Handle_Prs3d_Projector& aProjector, const Handle_Geom_Transformation& aTransformation, const Handle_Prs3d_Presentation& aPresentation)
+//=======================================================================
+//function : Compute
+//purpose  :
+//=======================================================================
+void AIS_ConnectedInteractive::Compute(const Handle(Prs3d_Projector)& aProjector, const Handle(Prs3d_Presentation)& aPresentation)
 {
-// Standard_NotImplemented::Raise("AIS_ConnectedInteractive::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
-  PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
+  updateShape (Standard_True);
+  Compute (aProjector, aPresentation, myShape);
 }
 
-void AIS_ConnectedInteractive::Compute(const Handle_Prs3d_Projector& aProjector, const Handle_Prs3d_Presentation& aPresentation)
+//=======================================================================
+//function : Compute
+//purpose  :
+//=======================================================================
+void AIS_ConnectedInteractive::Compute (const Handle(Prs3d_Projector)& theProjector,
+                                        const Handle(Prs3d_Presentation)& thePrs,
+                                        const TopoDS_Shape& theShape)
 {
-// Standard_NotImplemented::Raise("AIS_ConnectedInteractive::Compute(const Handle_Prs3d_Projector&, const Handle_Prs3d_Presentation&)");
- PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
+  AIS_Shape::computeHlrPresentation (theProjector, thePrs, theShape, myDrawer);
 }
 
-void AIS_ConnectedInteractive::Compute(const Handle_PrsMgr_PresentationManager2d& aPresentationManager2d, const Handle_Graphic2d_GraphicObject& aGraphicObject, const int anInteger)
+//=======================================================================
+//function : updateShape
+//purpose  : 
+//=======================================================================
+void AIS_ConnectedInteractive::updateShape (const Standard_Boolean isWithLocation)
 {
-// Standard_NotImplemented::Raise("AIS_ConnectedInteractive::Compute(const Handle_PrsMgr_PresentationManager2d&, const Handle_Graphic2d_GraphicObject&, const int)");
- PrsMgr_PresentableObject::Compute( aPresentationManager2d ,aGraphicObject,anInteger) ;
+  Handle(AIS_Shape) anAisShape = Handle(AIS_Shape)::DownCast (myReference);
+  if (anAisShape.IsNull())
+  {
+    return;
+  }
+  TopoDS_Shape aShape = anAisShape->Shape();
+  if (aShape.IsNull())
+  {
+    return;
+  }
+
+  if(!isWithLocation)
+  {
+    myShape = aShape;
+  }
+  else
+  {
+    myShape = aShape.Moved (TopLoc_Location (Transformation()));
+  }
 }
 
 //=======================================================================
 //function : ComputeSelection
 //purpose  : 
 //=======================================================================
-void AIS_ConnectedInteractive::ComputeSelection(const Handle(SelectMgr_Selection)& aSel,
-                                               const Standard_Integer aMode)
+void AIS_ConnectedInteractive::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, 
+                                                 const Standard_Integer theMode)
 {
-  if(!(HasLocation() ||HasConnection())) return;
-  
-  aSel->Clear();
-  if(!myReference->HasSelection(aMode))
-    myReference->UpdateSelection(aMode);
-  
-  
-//  static OSD_Timer KronSel;
-//  cout<<"debut calcul connexion primitives pour le mode "<<aMode<<endl;
-//  KronSel.Reset();
-//  KronSel.Start();
-  
-  const Handle(SelectMgr_Selection)& TheRefSel = myReference->Selection(aMode);
-  Handle(SelectMgr_EntityOwner) OWN = new SelectMgr_EntityOwner(this);
-  Handle(Select3D_SensitiveEntity) SE3D,SNew;
-  
-  if(TheRefSel->IsEmpty())
-    myReference->UpdateSelection(aMode);
-  for(TheRefSel->Init();TheRefSel->More();TheRefSel->Next()){
-    SE3D = *((Handle(Select3D_SensitiveEntity)*) &(TheRefSel->Sensitive()));
-    if(!SE3D.IsNull()){
-      SNew = SE3D->GetConnected(myLocation);
-      if(aMode==0)
-       SNew->Set(OWN);
-      aSel->Add(SNew);
+  if (!HasConnection())
+  {
+    return;
+  }
+
+  if (theMode != 0 && myReference->AcceptShapeDecomposition())
+  {
+    computeSubShapeSelection (theSelection, theMode);
+    return;
+  }
+
+  if (!myReference->HasSelection (theMode))
+  {
+    myReference->RecomputePrimitives (theMode);
+  }
+
+  const Handle(SelectMgr_Selection)& TheRefSel = myReference->Selection (theMode);
+  Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner (this);
+
+  TopLoc_Location aLocation (Transformation());
+  anOwner->SetLocation (aLocation);
+
+  if (TheRefSel->IsEmpty())
+  {
+    myReference->RecomputePrimitives (theMode);
+  }
+
+  for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (TheRefSel->Entities()); aSelEntIter.More(); aSelEntIter.Next())
+  {
+    if (Handle(Select3D_SensitiveEntity) aSensitive = Handle(Select3D_SensitiveEntity)::DownCast (aSelEntIter.Value()->BaseSensitive()))
+    {
+      // Get the copy of SE3D
+      if (Handle(Select3D_SensitiveEntity) aNewSensitive = aSensitive->GetConnected())
+      {
+        aNewSensitive->Set(anOwner);
+        theSelection->Add (aNewSensitive);
+      }
     }
   }
-//  KronSel.Stop();
-//  cout<<"fin calcul connexion primitives pour le mode "<<aMode<<endl;
-//  KronSel.Show();
 }
 
-void AIS_ConnectedInteractive::UpdateLocation()
-{
-// Standard_NotImplemented::Raise("AIS_ConnectedInteractive::UpdateLocation()");
- SelectMgr_SelectableObject::UpdateLocation() ;
-}
-void AIS_ConnectedInteractive::UpdateLocation(const Handle(SelectMgr_Selection)& Sel)
+//=======================================================================
+//function : ComputeSubShapeSelection 
+//purpose  :
+//=======================================================================
+void AIS_ConnectedInteractive::computeSubShapeSelection (const Handle(SelectMgr_Selection)& theSelection, 
+                                                         const Standard_Integer theMode)
 {
-// Standard_NotImplemented::Raise("AIS_ConnectedInteractive::UpdateLocation(const Handle(SelectMgr_Selection)& Sel)");
- SelectMgr_SelectableObject::UpdateLocation(Sel) ;
+  typedef NCollection_List<Handle(Select3D_SensitiveEntity)> SensitiveList;
+  typedef NCollection_DataMap<TopoDS_Shape, SensitiveList, TopTools_OrientedShapeMapHasher>
+    Shapes2EntitiesMap;
+
+  if (!myReference->HasSelection (theMode))
+  {
+    myReference->RecomputePrimitives (theMode);
+  }
+
+  const Handle(SelectMgr_Selection)& aRefSel = myReference->Selection (theMode);
+  if (aRefSel->IsEmpty() || aRefSel->UpdateStatus() == SelectMgr_TOU_Full)
+  {
+    myReference->RecomputePrimitives (theMode);
+  }
+
+  // Fill in the map of subshapes and corresponding sensitive entities associated with aMode
+  Shapes2EntitiesMap aShapes2EntitiesMap;
+  for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (aRefSel->Entities()); aSelEntIter.More(); aSelEntIter.Next())
+  {
+    if (Handle(Select3D_SensitiveEntity) aSE = Handle(Select3D_SensitiveEntity)::DownCast (aSelEntIter.Value()->BaseSensitive()))
+    {
+      if (Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast (aSE->OwnerId()))
+      {
+        const TopoDS_Shape& aSubShape = anOwner->Shape();
+        if(!aShapes2EntitiesMap.IsBound (aSubShape))
+        {
+          aShapes2EntitiesMap.Bind (aSubShape, SensitiveList());
+        }
+        aShapes2EntitiesMap (aSubShape).Append (aSE);
+      }
+    }
+  }
+
+  // Fill in selection from aShapes2EntitiesMap
+  for (Shapes2EntitiesMap::Iterator aMapIt (aShapes2EntitiesMap); aMapIt.More(); aMapIt.Next())
+  {
+    const SensitiveList& aSEList = aMapIt.Value();
+    Handle(StdSelect_BRepOwner) anOwner = new StdSelect_BRepOwner (aMapIt.Key(), this, aSEList.First()->OwnerId()->Priority(), Standard_True);
+    anOwner->SetLocation (Transformation());
+    for (SensitiveList::Iterator aListIt (aSEList); aListIt.More(); aListIt.Next())
+    {
+      if (Handle(Select3D_SensitiveEntity) aNewSE = aListIt.Value()->GetConnected())
+      {
+        aNewSE->Set (anOwner);
+        theSelection->Add (aNewSE);
+      }
+    }
+  }
+
+  StdSelect::SetDrawerForBRepOwner (theSelection, myDrawer);  
 }
-/*void AIS_ConnectedInteractive::UpdateLocation(const Handle_Prs3d_Presentation& aPresentation)
-{
-// Standard_NotImplemented::Raise("AIS_ConnectedInteractive::UpdateLocation(const Handle_Prs3d_Presentation&)");
- SelectMgr_SelectableObject::UpdateLocation(aPresentation) ;
-}*/