0024837: Visualization - revise design and implementation of connected Interactive...
[occt.git] / src / AIS / AIS_ConnectedInteractive.cxx
1 // Created on: 1997-01-08
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1997-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 <Standard_NotImplemented.hxx>
18
19 #include <AIS_ConnectedInteractive.ixx>
20 #include <SelectMgr_EntityOwner.hxx>
21 #include <Select3D_SensitiveEntity.hxx>
22 #include <Geom_Transformation.hxx>
23
24 #include <PrsMgr_ModedPresentation.hxx>
25 #include <PrsMgr_Presentation.hxx>
26
27 #include <StdSelect_BRepOwner.hxx>
28
29 #include <StdSelect.hxx>
30 #include <TopTools_IndexedMapOfShape.hxx>
31 #include <TopTools_OrientedShapeMapHasher.hxx>
32
33 #include <AIS_InteractiveContext.hxx>
34 #include <BRepTools.hxx>
35 #include <Precision.hxx>
36 #include <AIS_Drawer.hxx>
37 #include <TopAbs_ShapeEnum.hxx>
38 #include <StdPrs_WFDeflectionShape.hxx>
39 #include <StdPrs_HLRPolyShape.hxx>
40 #include <Prs3d_Drawer.hxx>
41
42 #include <AIS_Shape.hxx>
43
44 #include <NCollection_DataMap.hxx>
45
46
47 //=======================================================================
48 //function : AIS_ConnectedInteractive
49 //purpose  : 
50 //=======================================================================
51 AIS_ConnectedInteractive::AIS_ConnectedInteractive(const PrsMgr_TypeOfPresentation3d aTypeOfPresentation3d):
52 AIS_InteractiveObject(aTypeOfPresentation3d)
53 {
54   SetHilightMode(0);
55 }
56
57 //=======================================================================
58 //function : Type
59 //purpose  : 
60 //=======================================================================
61 AIS_KindOfInteractive AIS_ConnectedInteractive::Type() const
62 {
63   return AIS_KOI_Object;
64 }
65
66 Standard_Integer AIS_ConnectedInteractive::Signature() const
67 {
68   return 0;
69 }
70
71
72 //=======================================================================
73 //function : Connect
74 //purpose  : 
75 //=======================================================================
76 void AIS_ConnectedInteractive::Connect (const Handle(AIS_InteractiveObject)& theAnotherObj)
77 {
78   if (myReference == theAnotherObj) return;
79
80   Handle(AIS_ConnectedInteractive) aConnected = Handle(AIS_ConnectedInteractive)::DownCast (theAnotherObj);
81   if (!aConnected.IsNull())
82   {
83     myReference = aConnected->myReference;
84   }
85   else if (theAnotherObj->HasOwnPresentations())
86   {
87     myReference = theAnotherObj;
88   }
89
90   if (!myReference.IsNull())
91   {
92     myTypeOfPresentation3d = myReference->TypeOfPresentation3d();
93   }
94
95   theAnotherObj->AddChild (this);
96 }
97
98 //=======================================================================
99 //function : Connect
100 //purpose  : 
101 //=======================================================================
102 void AIS_ConnectedInteractive::Connect (const Handle(AIS_InteractiveObject)& theAnotherObj, 
103                                         const gp_Trsf&                       theLocation)
104 {
105   Connect (theAnotherObj);
106
107   SetLocalTransformation (theLocation);
108 }
109
110
111 //=======================================================================
112 //function : Disconnect
113 //purpose  :
114 //=======================================================================
115
116 void AIS_ConnectedInteractive::Disconnect()
117 {
118   for(Standard_Integer aPrsIter = 1; aPrsIter <= myPresentations.Length(); ++aPrsIter)
119   {
120     const Handle(PrsMgr_Presentation)& aPrs = myPresentations (aPrsIter).Presentation();
121     if (!aPrs.IsNull())
122     {
123       aPrs->Presentation()->DisconnectAll (Graphic3d_TOC_DESCENDANT);
124     }
125   }
126 }
127 //=======================================================================
128 //function : Compute
129 //purpose  :
130 //=======================================================================
131 void AIS_ConnectedInteractive::Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
132                                         const Handle(Prs3d_Presentation)&           thePrs,
133                                         const Standard_Integer                      theMode)
134 {
135   if (HasConnection())
136   {
137     thePrs->Clear (Standard_False);
138     thePrs->RemoveAll();
139
140     if (!myReference->HasInteractiveContext())
141     {
142       myReference->SetContext (GetContext());
143     }
144     thePrsMgr->Connect (this, myReference, theMode, theMode);
145     if (thePrsMgr->Presentation (myReference, theMode)->MustBeUpdated())
146     {
147       thePrsMgr->Update (myReference, theMode);
148     }
149   }
150
151   if (!thePrs.IsNull())
152   {
153     thePrs->ReCompute();
154   }
155 }
156
157 //=======================================================================
158 //function : Compute
159 //purpose  :
160 //=======================================================================
161 void AIS_ConnectedInteractive::Compute (const Handle(Prs3d_Projector)& theProjector,
162                                         const Handle(Geom_Transformation)& theTransformation,
163                                         const Handle(Prs3d_Presentation)& thePresentation)
164 {
165   updateShape (Standard_False);
166   if (myShape.IsNull())
167   {
168     return;
169   }
170   const TopLoc_Location& aLocation = myShape.Location();
171   TopoDS_Shape aShape = myShape.Located (TopLoc_Location (theTransformation->Trsf()) * aLocation);
172   Compute (theProjector, thePresentation, aShape);
173 }
174
175 //=======================================================================
176 //function : Compute
177 //purpose  :
178 //=======================================================================
179 void AIS_ConnectedInteractive::Compute(const Handle(Prs3d_Projector)& aProjector, const Handle(Prs3d_Presentation)& aPresentation)
180 {
181   updateShape (Standard_True);
182   Compute (aProjector, aPresentation, myShape);
183 }
184
185 //=======================================================================
186 //function : Compute
187 //purpose  :
188 //=======================================================================
189 void AIS_ConnectedInteractive::Compute (const Handle(Prs3d_Projector)& theProjector,
190                                         const Handle(Prs3d_Presentation)& thePresentation,
191                                         const TopoDS_Shape& theShape)
192 {
193   if (myShape.IsNull())
194   {
195     return;
196   }
197
198   switch (theShape.ShapeType())
199   {
200     case TopAbs_VERTEX:
201     case TopAbs_EDGE:
202     case TopAbs_WIRE:
203     {
204       thePresentation->SetDisplayPriority (4);
205       StdPrs_WFDeflectionShape::Add (thePresentation, theShape, myDrawer);
206       break;
207     }
208     default:
209     {
210       Handle(Prs3d_Drawer) aDefaultDrawer = GetContext()->DefaultDrawer();
211       if (aDefaultDrawer->DrawHiddenLine()) 
212       {
213         myDrawer->EnableDrawHiddenLine();
214       }
215       else 
216       {
217         myDrawer->DisableDrawHiddenLine();
218       }
219       
220       Aspect_TypeOfDeflection aPrevDeflection = aDefaultDrawer->TypeOfDeflection();
221       aDefaultDrawer->SetTypeOfDeflection(Aspect_TOD_RELATIVE);
222
223       // process HLRAngle and HLRDeviationCoefficient()
224       Standard_Real aPrevAngle = myDrawer->HLRAngle();
225       Standard_Real aNewAngle = aDefaultDrawer->HLRAngle();
226       if (Abs (aNewAngle - aPrevAngle) > Precision::Angular())
227       {
228         BRepTools::Clean (theShape);
229       }
230
231       myDrawer->SetHLRAngle (aNewAngle);
232       myDrawer->SetHLRDeviationCoefficient (aDefaultDrawer->HLRDeviationCoefficient());
233       StdPrs_HLRPolyShape::Add (thePresentation, theShape, myDrawer, theProjector);
234       aDefaultDrawer->SetTypeOfDeflection (aPrevDeflection);
235     }
236   }
237 }
238
239 //=======================================================================
240 //function : updateShape
241 //purpose  : 
242 //=======================================================================
243 void AIS_ConnectedInteractive::updateShape (const Standard_Boolean isWithLocation)
244 {
245   Handle(AIS_Shape) anAisShape = Handle(AIS_Shape)::DownCast (myReference);
246   if (anAisShape.IsNull())
247   {
248     return;
249   }
250  
251   TopoDS_Shape aShape = anAisShape->Shape();
252   if (aShape.IsNull())
253   {
254     return;
255   }
256
257   if(!isWithLocation)
258   {
259     myShape = aShape;
260   }
261   else
262   {
263     myShape = aShape.Moved (TopLoc_Location (Transformation()));
264   }
265 }
266
267 //=======================================================================
268 //function : ComputeSelection
269 //purpose  : 
270 //=======================================================================
271 void AIS_ConnectedInteractive::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, 
272                                                  const Standard_Integer theMode)
273 {
274   if (!HasConnection())
275   {
276     return;
277   }
278
279   if (theMode != 0 && myReference->AcceptShapeDecomposition())
280   {
281     computeSubShapeSelection (theSelection, theMode);
282     return;
283   }
284
285   if (!myReference->HasSelection (theMode))
286   {
287     myReference->UpdateSelection (theMode);
288   }
289
290   const Handle(SelectMgr_Selection)& TheRefSel = myReference->Selection (theMode);
291   Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner (this);
292   Handle(Select3D_SensitiveEntity) aSensitive, aNewSensitive;
293   
294   if (TheRefSel->IsEmpty())
295   {
296     myReference->UpdateSelection (theMode);
297   }
298
299   for (TheRefSel->Init(); TheRefSel->More(); TheRefSel->Next())
300   {
301     aSensitive = Handle(Select3D_SensitiveEntity)::DownCast (TheRefSel->Sensitive());
302     if (!aSensitive.IsNull())
303     {
304       TopLoc_Location aLocation (Transformation());
305       // Get the copy of SE3D
306       aNewSensitive = aSensitive->GetConnected (aLocation);
307
308       aNewSensitive->Set(anOwner);
309       // In case if SE3D caches some location-dependent data
310       // that must be updated after setting OWN
311       aNewSensitive->SetLocation (aLocation);
312
313       theSelection->Add (aNewSensitive);
314     }
315   }
316 }
317
318 //=======================================================================
319 //function : ComputeSubShapeSelection 
320 //purpose  :
321 //=======================================================================
322 void AIS_ConnectedInteractive::computeSubShapeSelection (const Handle(SelectMgr_Selection)& theSelection, 
323                                                          const Standard_Integer theMode)
324 {
325   typedef NCollection_List<Handle(Select3D_SensitiveEntity)> SensitiveList;
326   typedef NCollection_DataMap<TopoDS_Shape, SensitiveList, TopTools_OrientedShapeMapHasher>
327     Shapes2EntitiesMap;
328
329   if (!myReference->HasSelection (theMode))
330     myReference->UpdateSelection (theMode);
331    
332   const Handle(SelectMgr_Selection)& aRefSel = myReference->Selection (theMode);
333
334   if (aRefSel->IsEmpty() || aRefSel->UpdateStatus() == SelectMgr_TOU_Full)
335   {
336     myReference->UpdateSelection (theMode);
337   }
338   
339   Handle(StdSelect_BRepOwner) anOwner;
340   TopLoc_Location aDummyLoc;
341
342   Handle(Select3D_SensitiveEntity) aSE, aNewSE;
343   Shapes2EntitiesMap aShapes2EntitiesMap;
344
345   SensitiveList aSEList;
346   TopoDS_Shape aSubShape;
347
348   // Fill in the map of subshapes and corresponding 
349   // sensitive entities associated with aMode 
350   for (aRefSel->Init(); aRefSel->More(); aRefSel->Next())
351   {
352     aSE = Handle(Select3D_SensitiveEntity)::DownCast (aRefSel->Sensitive()); 
353     if(!aSE.IsNull())
354     {
355       anOwner = Handle(StdSelect_BRepOwner)::DownCast (aSE->OwnerId());
356       if(!anOwner.IsNull())
357       {
358         aSubShape = anOwner->Shape(); 
359         if(!aShapes2EntitiesMap.IsBound (aSubShape))
360         {
361           aShapes2EntitiesMap.Bind (aSubShape, aSEList);
362         }
363         aShapes2EntitiesMap (aSubShape).Append (aSE);
364       }
365     }
366   }
367
368   // Fill in selection from aShapes2EntitiesMap
369   for (Shapes2EntitiesMap::Iterator aMapIt (aShapes2EntitiesMap); aMapIt.More(); aMapIt.Next())
370   {
371     aSEList = aMapIt.Value();
372     anOwner = new StdSelect_BRepOwner (aMapIt.Key(), 
373                                        this, 
374                                        aSEList.First()->OwnerId()->Priority(), 
375                                        Standard_True);
376
377     for (SensitiveList::Iterator aListIt (aSEList); aListIt.More(); aListIt.Next())
378     {      
379       aSE = aListIt.Value();
380
381       TopLoc_Location aLocation (Transformation());
382       aNewSE = aSE->GetConnected (aDummyLoc);
383       aNewSE->Set (anOwner);
384       // In case if aSE caches some location-dependent data 
385       // that must be updated after setting anOwner
386       aNewSE->SetLocation (aLocation);
387
388       theSelection->Add (aNewSE);
389     }
390   }
391
392   StdSelect::SetDrawerForBRepOwner (theSelection, myDrawer);  
393 }