0023948: Wrong intersection between a surface of revolution and a plane.
[occt.git] / src / AIS / AIS_Selection.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <AIS_Selection.ixx>
16 #include <TCollection_AsciiString.hxx>
17 #include <TColStd_SequenceOfTransient.hxx>
18
19 #define BUC60953   // SAV_050701 : the array of selected objects has always the same length
20 // independently of number of objects selected. Thus, if there were selected
21 // more than MaxSizeOfResult objects we have got an exception.
22 // Moreover, Select method was optimized a little bit.
23 // Now it checks the state of incoming owner. If the state is 0
24 // there is no searching for object in <myresult> array.
25
26 #define OCC138
27
28 #define OCC189     //SAV: 18//03/02 array was replaced with list.
29
30 #define OCC1039    //SAV: 25/11/02 clearing selected objects if any on the AIS_Selection remove.
31
32 #define USE_MAP    //san : 18/04/03 USE_MAP - additional datamap is used to speed up access 
33 //to certain owners in <myresult> list
34
35 #ifdef BUC60953
36 #include <SelectMgr_EntityOwner.hxx>
37 #endif
38
39 #ifdef OCC138      //VTN Avoding infinit loop in AddOrRemoveSelected and AddOrRemoveCurrentObject methods.
40 #include <AIS_InteractiveObject.hxx>
41 #endif
42
43 #ifndef USE_MAP
44 #define MaxSizeOfResult 10000
45 #else
46 #define MaxSizeOfResult 100000
47 #endif
48
49 //current selection (handle)
50 static Handle(AIS_Selection) theCurrentSelection;
51 static void AIS_Sel_CurrentSelection (Handle(AIS_Selection)& InputSel)     
52 {
53   if(!InputSel.IsNull())
54     theCurrentSelection = InputSel;
55   else
56     InputSel = theCurrentSelection;
57 }
58
59 static TColStd_SequenceOfTransient&  AIS_Sel_GetSelections()
60 {
61   static TColStd_SequenceOfTransient Selections;
62   return Selections;
63 }
64
65 //=======================================================================
66 //function : AIS_Selection
67 //purpose  : 
68 //=======================================================================
69 AIS_Selection::AIS_Selection(const Standard_CString aName) :
70 myName(TCollection_AsciiString(aName)),
71 #if !defined USE_MAP && !defined OCC189
72 myresult(new TColStd_HArray1OfTransient(1,MaxSizeOfResult)),
73 #endif
74 myNb(0)
75 {
76 #ifdef USE_MAP 
77   myResultMap.ReSize( MaxSizeOfResult ); // for maximum performnace on medium selections ( < 100000 objects )
78 #endif
79 }
80
81 //=======================================================================
82 //function : CreateSelection
83 //purpose  : 
84 //=======================================================================
85 Standard_Boolean AIS_Selection::CreateSelection(const Standard_CString aName)
86
87   Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
88   if(!S.IsNull())
89     return Standard_False;
90   S = new AIS_Selection(aName);
91   AIS_Sel_GetSelections().Prepend(S);
92   AIS_Sel_CurrentSelection(S);
93   return Standard_True;
94 }
95
96
97 //=======================================================================
98 //function : Selection
99 //purpose  : 
100 //=======================================================================
101 Handle(AIS_Selection) AIS_Selection::Selection(const Standard_CString aName) 
102 {
103   Handle(AIS_Selection) S;
104   if(AIS_Sel_GetSelections().IsEmpty()) return S;
105   
106   Handle(Standard_Transient) curobj;
107   Handle(AIS_Selection) Sel;
108 //  Standard_Boolean found(Standard_False);
109   for(Standard_Integer I =1; I<= AIS_Sel_GetSelections().Length();I++){
110     curobj = AIS_Sel_GetSelections().Value(I);
111     Sel = *((Handle(AIS_Selection)*)&curobj);
112     if(Sel->myName.IsEqual(aName))
113       return Sel;
114   }
115   
116   return S;
117 }
118
119 //=======================================================================
120 //function : Find
121 //purpose  : 
122 //=======================================================================
123 Standard_Boolean AIS_Selection::Find(const Standard_CString aName) 
124 {
125   Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
126   return !S.IsNull();
127 }
128
129 //=======================================================================
130 //function : SetCurrentSelection
131 //purpose  : 
132 //=======================================================================
133 Standard_Boolean AIS_Selection::SetCurrentSelection (const Standard_CString aName) 
134 {  
135   AIS_Selection::CreateSelection(aName); 
136
137
138   Handle(AIS_Selection) anAISSelection = AIS_Selection::Selection(aName) ;
139   AIS_Sel_CurrentSelection ( anAISSelection ) ;
140   return Standard_True;
141 }
142
143 //=======================================================================
144 //function : Select
145 //purpose  : 
146 //=======================================================================
147 void AIS_Selection::Select() 
148 {
149   Handle(AIS_Selection) S;
150   AIS_Sel_CurrentSelection (S);
151   if(!S.IsNull()){
152     S->myNb=0;
153 #if defined OCC189 || defined USE_MAP
154     S->myresult.Clear();
155 #ifdef USE_MAP
156     S->myResultMap.Clear();
157 #endif
158 #endif
159   }
160 }
161
162 //=======================================================================
163 //function : CurrentSelection
164 //purpose  : 
165 //=======================================================================
166 Handle(AIS_Selection) AIS_Selection::CurrentSelection() {
167   Handle(AIS_Selection) S;
168   AIS_Sel_CurrentSelection (S);
169   return S;
170 }
171 //=======================================================================
172 //function : Select
173 //purpose  : 
174 //=======================================================================
175 AIS_SelectStatus AIS_Selection::Select(const Handle(Standard_Transient)& anObject) 
176 {
177   Handle(AIS_Selection) S;
178   AIS_Sel_CurrentSelection (S);
179   if(S.IsNull()) return AIS_SS_NotDone;
180   Handle(AIS_InteractiveObject) anAISObj;
181   Handle(SelectMgr_EntityOwner) owner = Handle(SelectMgr_EntityOwner)::DownCast( anObject );
182   if ( owner.IsNull() )
183     anAISObj = Handle(AIS_InteractiveObject)::DownCast( anObject );
184 #ifndef OCC189
185   TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
186   
187   Standard_Integer Found(-1);
188   Standard_Integer i ;
189
190 #ifdef BUC60953
191   
192   Standard_Boolean selected = Standard_False;
193   if ( !owner.IsNull() )
194     selected = owner->State() != 0;
195 #ifdef OCC138
196   else if(!anAISObj.IsNull())
197     selected = anAISObj->State();
198   }
199 #endif
200
201   if ( selected ) // looking up index of object
202 #endif
203
204   for( i=arr.Lower() && Found==-1;i<=S->myNb;i++){
205     if(arr(i)==anObject)
206       Found=i;
207   }
208   // If it is not inside, it is added...
209
210 #ifdef BUC60953
211   if ( !selected || Found == -1 ) {
212 #else
213   if(Found==-1){
214 #endif  
215     if((S->myNb)+1>arr.Length()){
216       Handle(TColStd_HArray1OfTransient) NiouTab = new TColStd_HArray1OfTransient(1,arr.Length()+MaxSizeOfResult);
217       for(i=arr.Lower();i<=S->myNb;i++){
218         const Handle(Standard_Transient)& T = S->myresult->Value(i);
219         NiouTab->SetValue(i,T);
220       }
221 #ifdef BUC60953
222       S->myresult = NiouTab;
223 #endif
224     }
225     (S->myNb)++;
226     S->myresult->SetValue(S->myNb,anObject);
227     return AIS_SS_Added;
228   }
229   // it was inside and it is removed...
230   for(i=Found;i<=S->myNb;i++)
231     arr(i)=arr(i+1);
232   S->myNb--;
233 #elif !defined USE_MAP //OCC189
234   AIS_NListTransient::Iterator anIter ( S->myresult );
235   for ( ; anIter.More(); anIter.Next() )
236     if ( anIter.Value() == anObject ) {
237       S->myresult.Remove( anIter );
238       return AIS_SS_Removed;
239     }
240       
241   S->myresult.Append( anObject );
242   return AIS_SS_Added;
243 #else //USE_MAP
244   if ( S->myResultMap.IsBound( anObject ) ){
245     AIS_NListTransient::Iterator aListIter = S->myResultMap.Find( anObject );
246 //skt-----------------------------------------------------------------
247     if( S->myIterator == aListIter ) {
248       if( S->myIterator.More() )
249           S->myIterator.Next();
250       else
251           S->myIterator = AIS_NListTransient::Iterator();
252     }
253 //--------------------------------------------------------------------
254 #ifdef BUC60953
255     // In the mode of advanced mesh selection only one owner is created
256     // for all selection modes. It is necessary to check the current detected
257     // entity and remove the owner from map only if the detected entity is
258     // the same as previous selected (IsForcedHilight call)
259     if( !anAISObj.IsNull() || ( !owner.IsNull() && !owner->IsForcedHilight() ) )
260     {
261 #endif  
262       S->myresult.Remove( aListIter );
263       S->myResultMap.UnBind( anObject );
264     
265       // update list iterator for next object in <myresult> list if any
266       if ( aListIter.More() ){
267         const Handle(Standard_Transient)& aNextObject = aListIter.Value();
268         if ( S->myResultMap.IsBound( aNextObject ) )
269           S->myResultMap( aNextObject ) = aListIter;
270         else
271           S->myResultMap.Bind( aNextObject, aListIter );
272       }
273       return AIS_SS_Removed;
274     }
275     else
276       return AIS_SS_Added;
277   }
278   
279   AIS_NListTransient::Iterator aListIter;
280   S->myresult.Append( anObject, aListIter );
281   S->myResultMap.Bind( anObject, aListIter );
282   return AIS_SS_Added;
283 #endif //USE_MAP  
284 }
285
286 //=======================================================================
287 //function : AddSelect
288 //purpose  : Always add int the selection
289 //=======================================================================
290 AIS_SelectStatus AIS_Selection::AddSelect(const Handle(Standard_Transient)& anObject) 
291 {
292   Handle(AIS_Selection) S;
293   AIS_Sel_CurrentSelection (S);
294   if(S.IsNull()) return AIS_SS_NotDone;
295
296 #ifndef OCC189
297   TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
298   Standard_Integer i;
299   if((S->myNb)+1>arr.Length()){
300       Handle(TColStd_HArray1OfTransient) NiouTab = new TColStd_HArray1OfTransient(1,arr.Length()+MaxSizeOfResult);
301       for(i=arr.Lower();i<=S->myNb;i++){
302         const Handle(Standard_Transient)& T = S->myresult->Value(i);
303         NiouTab->SetValue(i,T);
304       }
305       S->myresult = NiouTab;
306   }
307   (S->myNb)++;
308   S->myresult->SetValue(S->myNb,anObject);
309 #elif !defined USE_MAP //OCC189
310   S->myresult.Append( anObject );
311 #else //USE_MAP
312   if ( S->myResultMap.IsBound( anObject ) )
313     return AIS_SS_NotDone;
314       
315   AIS_NListTransient::Iterator aListIter;
316   S->myresult.Append( anObject, aListIter );
317   S->myResultMap.Bind( anObject, aListIter );
318 #endif
319   return AIS_SS_Added;
320 }
321
322
323 //=======================================================================
324 //function : ClearAndSelect
325 //purpose  : 
326 //=======================================================================
327
328 void AIS_Selection::ClearAndSelect(const Handle(Standard_Transient)& anObject) {
329   Handle(AIS_Selection) S;
330   AIS_Sel_CurrentSelection (S);
331   if(S.IsNull()) return;
332   
333   Select();
334   Select(anObject);
335
336 }
337
338
339 //=======================================================================
340 //function : Extent
341 //purpose  : 
342 //=======================================================================
343 Standard_Integer AIS_Selection::Extent() {
344   Handle(AIS_Selection) S;
345   AIS_Sel_CurrentSelection (S);
346 #if !defined OCC189 && !defined USE_MAP
347   return S->myNb;
348 #else
349   return S->myresult.Extent();
350 #endif
351 }
352
353 //=======================================================================
354 //function : Single
355 //purpose  : 
356 //=======================================================================
357 Handle(Standard_Transient)  AIS_Selection::Single() 
358 {
359   Handle(AIS_Selection) S;
360   AIS_Sel_CurrentSelection (S);
361   
362   S->Init();
363   return S->Value();
364 }
365 //=======================================================================
366 //function : IsSelected
367 //purpose  : 
368 //=======================================================================
369 Standard_Boolean AIS_Selection::IsSelected(const Handle(Standard_Transient)& anObject)
370 {
371   Handle(AIS_Selection) S;
372   AIS_Sel_CurrentSelection (S);
373   if(S.IsNull()) return Standard_False;
374 #ifndef USE_MAP  
375   for(S->Init();S->More();S->Next()){
376     if(S->Value()==anObject)
377       return Standard_True;
378   }
379   return Standard_False;
380 #else
381   return S->myResultMap.IsBound( anObject );
382 #endif
383 }
384
385 //=======================================================================
386 //function : Index
387 //purpose  : 
388 //=======================================================================
389
390 Standard_Integer AIS_Selection::Index(const Standard_CString aName)
391 {
392   Handle (Standard_Transient) curobj;
393   for(Standard_Integer I =1; I<= AIS_Sel_GetSelections().Length();I++){
394     curobj = AIS_Sel_GetSelections().Value(I);
395     if((*((Handle(AIS_Selection)*)&curobj))->myName.IsEqual(aName))
396       return I;
397   }
398   return 0;
399 }
400
401 //=======================================================================
402 //function : Remove
403 //purpose  : 
404 //=======================================================================
405
406 void AIS_Selection::Remove(const Standard_CString aName) 
407 {
408   Standard_Integer I = AIS_Selection::Index(aName);
409   if(I!=0) {
410 #ifdef OCC1039
411     Handle(AIS_Selection) selection = Handle(AIS_Selection)::DownCast( AIS_Sel_GetSelections().Value(I) );
412     Standard_Integer stored = selection->NbStored();
413     if ( stored )
414       selection->Select();
415 #endif
416     AIS_Sel_GetSelections().Remove(I);
417   }
418 }
419
420 // clean the static current selection handle
421 void AIS_Selection::ClearCurrentSelection()
422 {
423     theCurrentSelection.Nullify();
424 }
425