0024623: Visualization - improve selection mechanism
[occt.git] / src / StdSelect / StdSelect_BRepSelectionTool.cxx
1 // Created on: 1995-03-14
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1995-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 <StdSelect_BRepSelectionTool.ixx>
18 #include <GeomAdaptor_Curve.hxx>
19 #include <BRepAdaptor_Curve.hxx>
20 #include <TopTools_IndexedMapOfShape.hxx>
21 #include <TopExp.hxx>
22 #include <TopExp_Explorer.hxx>
23 #include <BRepTools_WireExplorer.hxx>
24 #include <Select3D_SensitivePoint.hxx>
25 #include <StdSelect_BRepOwner.hxx>
26 #include <TopoDS.hxx>
27 #include <BRepAdaptor_Curve.hxx>
28 #include <BRepAdaptor_Surface.hxx>
29 #include <GeomAbs_SurfaceType.hxx>
30 #include <BRepBndLib.hxx>
31 #include <Bnd_Box.hxx>
32 #include <BRep_Tool.hxx>
33 #include <Geom_Circle.hxx>
34 #include <Select3D_SensitiveEntity.hxx>
35 #include <Select3D_SensitiveCircle.hxx>
36 #include <Select3D_SensitiveCurve.hxx>
37 #include <Select3D_SensitiveSegment.hxx>
38 #include <Select3D_SensitiveWire.hxx>
39 #include <Select3D_SensitiveFace.hxx>
40 #include <Select3D_SensitiveBox.hxx>
41 #include <Select3D_SensitiveTriangulation.hxx>
42 #include <Select3D_SensitiveTriangle.hxx>
43 #include <Select3D_SensitiveGroup.hxx>
44 #include <SelectMgr_Selection.hxx>
45 #include <TColgp_HArray1OfPnt.hxx>
46 #include <TColgp_SequenceOfPnt.hxx>
47 #include <TColStd_Array1OfReal.hxx>
48 #include <BRep_Tool.hxx>
49 #include <BRepTools.hxx>
50 #include <Select3D_TypeOfSensitivity.hxx>
51 #include <Precision.hxx>
52 #include <gp_Circ.hxx>
53 #include <GCPnts_TangentialDeflection.hxx>
54 #include <TopoDS_Wire.hxx>
55 #include <Poly_Array1OfTriangle.hxx>
56 #include <Poly_Polygon3D.hxx>
57 #include <Poly_PolygonOnTriangulation.hxx>
58 #include <Poly_Triangulation.hxx>
59 #include <BRepMesh_IncrementalMesh.hxx>
60 #include <Standard_NullObject.hxx>
61 #include <Standard_ErrorHandler.hxx>
62
63 #define BVH_PRIMITIVE_LIMIT 800000
64
65 //==================================================
66 // function: preBuildBVH
67 // purpose : Pre-builds BVH tree for heavyweight
68 //           sensitive entities with sub-elements
69 //           amount more than BVH_PRIMITIVE_LIMIT
70 //==================================================
71 void StdSelect_BRepSelectionTool::preBuildBVH (const Handle(SelectMgr_Selection)& theSelection)
72 {
73   for (theSelection->Init(); theSelection->More(); theSelection->Next())
74   {
75     const Handle(SelectBasics_SensitiveEntity)& aSensitive = theSelection->Sensitive()->BaseSensitive();
76     if (aSensitive->NbSubElements() >= BVH_PRIMITIVE_LIMIT)
77     {
78       aSensitive->BVH();
79     }
80
81     if (aSensitive->IsInstance ("Select3D_SensitiveGroup"))
82     {
83       const Handle(Select3D_SensitiveGroup)& aGroup = Handle(Select3D_SensitiveGroup)::DownCast (aSensitive);
84       const Select3D_EntitySequence& aSubEntities = aGroup->GetEntities();
85       for (Select3D_EntitySequenceIter aSubEntitiesIter (aSubEntities); aSubEntitiesIter.More(); aSubEntitiesIter.Next())
86       {
87         const Handle(Select3D_SensitiveEntity)& aSubEntity = aSubEntitiesIter.Value();
88         if (aSubEntity->NbSubElements() >= BVH_PRIMITIVE_LIMIT)
89         {
90           aSubEntity->BVH();
91         }
92       }
93     }
94   }
95 }
96
97 //==================================================
98 // Function: Load
99 // Purpose :
100 //==================================================
101 void StdSelect_BRepSelectionTool
102 ::Load (const Handle(SelectMgr_Selection)& theSelection,
103         const TopoDS_Shape& theShape,
104         const TopAbs_ShapeEnum theType,
105         const Standard_Real theDeflection,
106         const Standard_Real theDeviationAngle,
107         const Standard_Boolean isAutoTriangulation,
108         const Standard_Integer thePriority,
109         const Standard_Integer theNbPOnEdge,
110         const Standard_Real theMaxParam)
111 {
112   Standard_Integer aPriority = (thePriority == -1) ? GetStandardPriority (theShape, theType) : thePriority;
113
114   if( isAutoTriangulation && !BRepTools::Triangulation (theShape, Precision::Infinite()) )
115   {
116     BRepMesh_IncrementalMesh aMesher(theShape, theDeflection, Standard_False, theDeviationAngle);
117   }
118
119   Handle(StdSelect_BRepOwner) aBrepOwner;
120   switch (theType)
121   {
122     case TopAbs_VERTEX:
123     case TopAbs_EDGE:
124     case TopAbs_WIRE:
125     case TopAbs_FACE:
126     case TopAbs_SHELL:
127     case TopAbs_SOLID:
128     case TopAbs_COMPSOLID:
129     {
130       TopTools_IndexedMapOfShape aSubShapes;
131       TopExp::MapShapes (theShape, theType, aSubShapes);
132
133       Standard_Boolean isComesFromDecomposition = !((aSubShapes.Extent() == 1) && (theShape == aSubShapes (1)));
134       for (Standard_Integer aShIndex = 1; aShIndex <= aSubShapes.Extent(); ++aShIndex)
135       {
136         const TopoDS_Shape& aSubShape = aSubShapes (aShIndex);
137         aBrepOwner = new StdSelect_BRepOwner (aSubShape, aPriority, isComesFromDecomposition);
138         ComputeSensitive (aSubShape, aBrepOwner,
139                           theSelection,
140                           theDeflection,
141                           theDeviationAngle,
142                           theNbPOnEdge,
143                           theMaxParam,
144                           isAutoTriangulation);
145       }
146       break;
147     }
148     default:
149     {
150       aBrepOwner = new StdSelect_BRepOwner (theShape, aPriority);
151       ComputeSensitive (theShape, aBrepOwner,
152                         theSelection,
153                         theDeflection,
154                         theDeviationAngle,
155                         theNbPOnEdge,
156                         theMaxParam,
157                         isAutoTriangulation);
158     }
159   }
160 }
161
162 //==================================================
163 // Function: Load
164 // Purpose :
165 //==================================================
166 void StdSelect_BRepSelectionTool
167 ::Load (const Handle(SelectMgr_Selection)& theSelection,
168         const Handle(SelectMgr_SelectableObject)& theSelectableObj,
169         const TopoDS_Shape& theShape,
170         const TopAbs_ShapeEnum theType,
171         const Standard_Real theDeflection,
172         const Standard_Real theDeviationAngle,
173         const Standard_Boolean isAutoTriangulation,
174         const Standard_Integer thePriority,
175         const Standard_Integer theNbPOnEdge,
176         const Standard_Real theMaxParam)
177 {
178   Load (theSelection,
179         theShape,
180         theType,
181         theDeflection,
182         theDeviationAngle,
183         isAutoTriangulation,
184         thePriority,
185         theNbPOnEdge,
186         theMaxParam);
187
188   // loading of selectables...
189   for (theSelection->Init(); theSelection->More(); theSelection->Next())
190   {
191     Handle(SelectMgr_EntityOwner) anOwner
192       = Handle(SelectMgr_EntityOwner)::DownCast (theSelection->Sensitive()->BaseSensitive()->OwnerId());
193     anOwner->Set (theSelectableObj);
194   }
195
196   preBuildBVH (theSelection);
197 }
198
199 //==================================================
200 // Function: ComputeSensitive
201 // Purpose :
202 //==================================================
203 void StdSelect_BRepSelectionTool
204 ::ComputeSensitive (const TopoDS_Shape& theShape,
205                     const Handle(StdSelect_BRepOwner)& theOwner,
206                     const Handle(SelectMgr_Selection)& theSelection,
207                     const Standard_Real theDeflection,
208                     const Standard_Real theDeviationAngle,
209                     const Standard_Integer theNbPOnEdge,
210                     const Standard_Real theMaxParam,
211                     const Standard_Boolean isAutoTriangulation)
212 {
213   switch (theShape.ShapeType())
214   {
215     case TopAbs_VERTEX:
216     {
217       theSelection->Add (new Select3D_SensitivePoint
218                          (theOwner, BRep_Tool::Pnt (TopoDS::Vertex (theShape))));
219       break;
220     }
221     case TopAbs_EDGE:
222     {
223       Handle(Select3D_SensitiveEntity) aSensitive;
224       GetEdgeSensitive (theShape, theOwner, theSelection,
225                         theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam,
226                         aSensitive);
227       if (!aSensitive.IsNull())
228       {
229         theSelection->Add (aSensitive);
230       }
231       break;
232     }
233     case TopAbs_WIRE:
234     {
235       BRepTools_WireExplorer aWireExp (TopoDS::Wire (theShape));
236       Handle (Select3D_SensitiveEntity) aSensitive;
237       Handle (Select3D_SensitiveWire) aWireSensitive = new Select3D_SensitiveWire (theOwner);
238       theSelection->Add (aWireSensitive);
239       while (aWireExp.More())
240       {
241         GetEdgeSensitive (aWireExp.Current(), theOwner, theSelection,
242                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam,
243                           aSensitive);
244         if (!aSensitive.IsNull())
245         {
246           aWireSensitive->Add (aSensitive);
247         }
248         aWireExp.Next();
249       }
250       break;
251     }
252     case TopAbs_FACE:
253     {
254       const TopoDS_Face& aFace = TopoDS::Face (theShape);
255       Select3D_EntitySequence aSensitiveList;
256       GetSensitiveForFace (aFace, theOwner,
257                            aSensitiveList,
258                            isAutoTriangulation, theNbPOnEdge, theMaxParam);
259       for (Select3D_EntitySequenceIter aSensIter (aSensitiveList);
260            aSensIter.More(); aSensIter.Next())
261       {
262         theSelection->Add (aSensIter.Value());
263       }
264       break;
265     }
266     case TopAbs_SHELL:
267     case TopAbs_SOLID:
268     case TopAbs_COMPSOLID:
269     {
270       TopTools_IndexedMapOfShape aSubfacesMap;
271       TopExp::MapShapes (theShape, TopAbs_FACE, aSubfacesMap);
272       for (Standard_Integer aShIndex = 1; aShIndex <= aSubfacesMap.Extent(); ++aShIndex)
273       {
274         ComputeSensitive (aSubfacesMap (aShIndex), theOwner,
275                           theSelection,
276                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
277       }
278       break;
279     }
280     case TopAbs_COMPOUND:
281     default:
282     {
283       TopExp_Explorer anExp;
284       // sub-vertices
285       for (anExp.Init (theShape, TopAbs_VERTEX, TopAbs_EDGE); anExp.More(); anExp.Next())
286       {
287         ComputeSensitive (anExp.Current(), theOwner,
288                           theSelection,
289                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
290       }
291       // sub-edges
292       for (anExp.Init (theShape, TopAbs_EDGE, TopAbs_FACE); anExp.More(); anExp.Next())
293       {
294         ComputeSensitive (anExp.Current(), theOwner,
295                           theSelection,
296                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
297       }
298       // sub-wires
299       for (anExp.Init (theShape, TopAbs_WIRE, TopAbs_FACE); anExp.More(); anExp.Next())
300       {
301         ComputeSensitive (anExp.Current(), theOwner,
302                           theSelection,
303                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
304       }
305
306       // sub-faces
307       TopTools_IndexedMapOfShape aSubfacesMap;
308       TopExp::MapShapes (theShape, TopAbs_FACE, aSubfacesMap);
309       for (Standard_Integer aShIndex = 1; aShIndex <= aSubfacesMap.Extent(); ++aShIndex)
310       {
311         ComputeSensitive (aSubfacesMap (aShIndex), theOwner,
312                           theSelection,
313                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
314       }
315     }
316   }
317 }
318
319 //==================================================
320 // Function: GetPointsFromPolygon
321 // Purpose :
322 //==================================================
323 static Handle(TColgp_HArray1OfPnt) GetPointsFromPolygon (const TopoDS_Edge& theEdge,
324                                                          const Standard_Real theDeflection)
325 {
326   Handle(TColgp_HArray1OfPnt) aResultPoints;
327
328   Standard_Real fi, la;
329   Handle(Geom_Curve) CC3d = BRep_Tool::Curve (theEdge, fi, la);
330
331   TopLoc_Location aLocation;
332   Handle(Poly_Polygon3D) aPolygon = BRep_Tool::Polygon3D (theEdge, aLocation);
333   if (!aPolygon.IsNull())
334   {
335     Standard_Boolean isOK = aPolygon->Deflection() <= theDeflection;
336     isOK = isOK || (CC3d.IsNull());
337     if (isOK)
338     {
339       const TColgp_Array1OfPnt& aNodes = aPolygon->Nodes();
340       aResultPoints = new TColgp_HArray1OfPnt (1, aNodes.Length());
341       if (aLocation.IsIdentity())
342       {
343         for (Standard_Integer aNodeId (aNodes.Lower()), aPntId (1); aNodeId <= aNodes.Upper(); ++aNodeId, ++aPntId)
344         {
345           aResultPoints->SetValue (aPntId, aNodes.Value (aNodeId));
346         }
347       }
348       else
349       {
350         for (Standard_Integer aNodeId (aNodes.Lower()), aPntId (1); aNodeId <= aNodes.Upper(); ++aNodeId, ++aPntId)
351         {
352           aResultPoints->SetValue (aPntId, aNodes.Value (aNodeId).Transformed (aLocation));
353         }
354       }
355       return aResultPoints;
356     }
357   }
358
359   Handle(Poly_Triangulation) aTriangulation;
360   Handle(Poly_PolygonOnTriangulation) anHIndices;
361   BRep_Tool::PolygonOnTriangulation (theEdge, anHIndices, aTriangulation, aLocation);
362   if (!anHIndices.IsNull())
363   {
364     Standard_Boolean isOK = anHIndices->Deflection() <= theDeflection;
365     isOK = isOK || (CC3d.IsNull());
366     if (isOK)
367     {
368       const TColStd_Array1OfInteger& anIndices = anHIndices->Nodes();
369       const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
370
371       aResultPoints = new TColgp_HArray1OfPnt (1, anIndices.Length());
372
373       if (aLocation.IsIdentity())
374       {
375         for (Standard_Integer anIndex (anIndices.Lower()), aPntId (1); anIndex <= anIndices.Upper(); ++anIndex, ++aPntId)
376         {
377           aResultPoints->SetValue (aPntId, aNodes (anIndices (anIndex)));
378         }
379       }
380       else
381       {
382         for (Standard_Integer anIndex (anIndices.Lower()), aPntId (1); anIndex <= anIndices.Upper(); ++anIndex, ++aPntId)
383         {
384           aResultPoints->SetValue (aPntId, aNodes (anIndices (anIndex)).Transformed (aLocation));
385         }
386       }
387       return aResultPoints;
388     }
389   }
390   return aResultPoints;
391 }
392
393 //==================================================
394 // Function: FindLimits
395 // Purpose :
396 //==================================================
397 static Standard_Boolean FindLimits (const Adaptor3d_Curve& theCurve,
398                                     const Standard_Real    theLimit,
399                                           Standard_Real&   theFirst,
400                                           Standard_Real&   theLast)
401 {
402   theFirst = theCurve.FirstParameter();
403   theLast  = theCurve.LastParameter();
404   Standard_Boolean isFirstInf = Precision::IsNegativeInfinite (theFirst);
405   Standard_Boolean isLastInf  = Precision::IsPositiveInfinite (theLast);
406   if (isFirstInf || isLastInf)
407   {
408     gp_Pnt aPnt1, aPnt2;
409     Standard_Real aDelta = 1.0;
410     Standard_Integer anIterCount = 0;
411     if (isFirstInf && isLastInf)
412     {
413       do {
414         if (anIterCount++ >= 100000) return Standard_False;
415         aDelta *= 2.0;
416         theFirst = - aDelta;
417         theLast  =   aDelta;
418         theCurve.D0 (theFirst, aPnt1);
419         theCurve.D0 (theLast,  aPnt2);
420       } while (aPnt1.Distance (aPnt2) < theLimit);
421     }
422     else if (isFirstInf)
423     {
424       theCurve.D0 (theLast, aPnt2);
425       do {
426         if (anIterCount++ >= 100000) return Standard_False;
427         aDelta *= 2.0;
428         theFirst = theLast - aDelta;
429         theCurve.D0 (theFirst, aPnt1);
430       } while (aPnt1.Distance (aPnt2) < theLimit);
431     }
432     else if (isLastInf)
433     {
434       theCurve.D0 (theFirst, aPnt1);
435       do {
436         if (anIterCount++ >= 100000) return Standard_False;
437         aDelta *= 2.0;
438         theLast = theFirst + aDelta;
439         theCurve.D0 (theLast, aPnt2);
440       } while (aPnt1.Distance (aPnt2) < theLimit);
441     }
442   }
443   return Standard_True;
444 }
445
446 //=====================================================
447 // Function : GetEdgeSensitive
448 // Purpose  : create a sensitive edge to add it
449 //            in computeselection to "aselection" (case of selection of an edge)
450 //            or to "aSensitiveWire" (case of selection of a wire; in this case,
451 //            the sensitive wire is added to "aselection" )
452 //            odl - for selection by rectangle -
453 //=====================================================
454 void StdSelect_BRepSelectionTool
455 ::GetEdgeSensitive (const TopoDS_Shape& theShape,
456                     const Handle(StdSelect_BRepOwner)& theOwner,
457                     const Handle(SelectMgr_Selection)& theSelection,
458                     const Standard_Real theDeflection,
459                     const Standard_Real theDeviationAngle,
460                     const Standard_Integer theNbPOnEdge,
461                     const Standard_Real theMaxParam,
462                     Handle(Select3D_SensitiveEntity)& theSensitive)
463 {
464   const TopoDS_Edge& anEdge = TopoDS::Edge (theShape);
465   BRepAdaptor_Curve cu3d;
466   try {
467     OCC_CATCH_SIGNALS
468     cu3d.Initialize (anEdge);
469   } catch (Standard_NullObject) {
470     return;
471   }
472
473   // try to get points from existing polygons
474   Handle(TColgp_HArray1OfPnt) aPoints = GetPointsFromPolygon (anEdge, theDeflection);
475   if (!aPoints.IsNull() && aPoints->Length() > 0)
476   {
477     theSensitive = new Select3D_SensitiveCurve (theOwner, aPoints);
478     return;
479   }
480
481   Standard_Real aParamFirst = cu3d.FirstParameter();
482   Standard_Real aParamLast  = cu3d.LastParameter();
483   switch (cu3d.GetType())
484   {
485     case GeomAbs_Line:
486     {
487       BRep_Tool::Range (anEdge, aParamFirst, aParamLast);
488       theSensitive = new Select3D_SensitiveSegment (theOwner,
489                                                     cu3d.Value (aParamFirst),
490                                                     cu3d.Value (aParamLast));
491       break;
492     }
493     case GeomAbs_Circle:
494     {
495       Handle (Geom_Circle) aCircle = new Geom_Circle (cu3d.Circle());
496       if (aCircle->Radius() <= Precision::Confusion())
497       {
498         theSelection->Add (new Select3D_SensitivePoint (theOwner, aCircle->Location()));
499       }
500       else
501       {
502         theSensitive = new Select3D_SensitiveCircle (theOwner, aCircle,
503                                                      aParamFirst, aParamLast, Standard_False, 16);
504       }
505       break;
506     }
507     default:
508     {
509       // reproduce drawing behaviour
510       // TODO: remove copy-paste from StdPrs_Curve and some others...
511       if (FindLimits (cu3d, theMaxParam, aParamFirst, aParamLast))
512       {
513         Standard_Integer aNbIntervals = cu3d.NbIntervals (GeomAbs_C1);
514         TColStd_Array1OfReal anIntervals (1, aNbIntervals + 1);
515         cu3d.Intervals (anIntervals, GeomAbs_C1);
516         Standard_Real aV1, aV2;
517         Standard_Integer aNumberOfPoints;
518         TColgp_SequenceOfPnt aPointsSeq;
519         for (Standard_Integer anIntervalId = 1; anIntervalId <= aNbIntervals; ++anIntervalId)
520         {
521           aV1 = anIntervals (anIntervalId);
522           aV2 = anIntervals (anIntervalId + 1);
523           if (aV2 > aParamFirst && aV1 < aParamLast)
524           {
525             aV1 = Max (aV1, aParamFirst);
526             aV2 = Min (aV2, aParamLast);
527
528             GCPnts_TangentialDeflection anAlgo (cu3d, aV1, aV2, theDeviationAngle, theDeflection);
529             aNumberOfPoints = anAlgo.NbPoints();
530
531             for (Standard_Integer aPntId = 1; aPntId < aNumberOfPoints; ++aPntId)
532             {
533               aPointsSeq.Append (anAlgo.Value (aPntId));
534             }
535             if (aNumberOfPoints > 0 && anIntervalId == aNbIntervals)
536             {
537               aPointsSeq.Append (anAlgo.Value (aNumberOfPoints));
538             }
539           }
540         }
541
542         aPoints = new TColgp_HArray1OfPnt (1, aPointsSeq.Length());
543         for (Standard_Integer aPntId = 1; aPntId <= aPointsSeq.Length(); ++aPntId)
544         {
545           aPoints->SetValue (aPntId, aPointsSeq.Value (aPntId));
546         }
547         theSensitive = new Select3D_SensitiveCurve (theOwner, aPoints);
548         break;
549       }
550
551       // simple subdivisions
552       Standard_Integer nbintervals = 1;
553       if (cu3d.GetType() == GeomAbs_BSplineCurve)
554       {
555         nbintervals = cu3d.NbKnots() - 1;
556         nbintervals = Max (1, nbintervals / 3);
557       }
558
559       Standard_Real aParam;
560       Standard_Integer aPntNb = Max (2, theNbPOnEdge * nbintervals);
561       Standard_Real aParamDelta = (aParamLast - aParamFirst) / (aPntNb - 1);
562       Handle(TColgp_HArray1OfPnt) aPointArray = new TColgp_HArray1OfPnt (1, aPntNb);
563       for (Standard_Integer aPntId = 1; aPntId <= aPntNb; ++aPntId)
564       {
565         aParam = aParamFirst + aParamDelta * (aPntId - 1);
566         aPointArray->SetValue (aPntId, cu3d.Value (aParam));
567       }
568       theSensitive = new Select3D_SensitiveCurve (theOwner, aPointArray);
569     }
570     break;
571   }
572 }
573
574 //=====================================================
575 // Function : GetStandardPriority
576 // Purpose  :
577 //=====================================================
578 Standard_Integer StdSelect_BRepSelectionTool::GetStandardPriority (const TopoDS_Shape& theShape,
579                                                                    const TopAbs_ShapeEnum theType)
580 {
581   switch (theType)
582   {
583     case TopAbs_VERTEX: return 8;
584     case TopAbs_EDGE:   return 7;
585     case TopAbs_WIRE:   return 6;
586     case TopAbs_FACE:   return 5;
587     case TopAbs_SHAPE:
588     default:
589       switch (theShape.ShapeType())
590       {
591         case TopAbs_VERTEX:    return 9;
592         case TopAbs_EDGE:      return 8;
593         case TopAbs_WIRE:      return 7;
594         case TopAbs_FACE:      return 6;
595         case TopAbs_SHELL:     return 5;
596         case TopAbs_COMPOUND:
597         case TopAbs_COMPSOLID:
598         case TopAbs_SOLID:
599         case TopAbs_SHAPE:
600         default:
601           return 4;
602       }
603   }
604 }
605
606 //=======================================================================
607 //function : GetSensitiveEntityForFace
608 //purpose  :
609 //=======================================================================
610 Standard_Boolean StdSelect_BRepSelectionTool
611 ::GetSensitiveForFace (const TopoDS_Face& theFace,
612                        const Handle(StdSelect_BRepOwner)& theOwner,
613                        Select3D_EntitySequence& theSensitiveList,
614                        const Standard_Boolean /*theAutoTriangulation*/,
615                        const Standard_Integer NbPOnEdge,
616                        const Standard_Real    theMaxParam,
617                        const Standard_Boolean theInteriorFlag)
618 {
619   // check if there is triangulation of the face...
620   TopLoc_Location aLoc;
621   Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (theFace, aLoc);
622
623   if (!aTriangulation.IsNull())
624   {
625     Handle(Select3D_SensitiveTriangulation) STG = new Select3D_SensitiveTriangulation (theOwner, aTriangulation, aLoc, theInteriorFlag);
626     theSensitiveList.Append (STG);
627     return Standard_True;
628   }
629
630   // for faces with triangulation bugs or without autotriangulation ....
631   // very ugly and should not even exist ...
632   BRepAdaptor_Surface BS;
633   BS.Initialize (theFace);
634
635   Standard_Real FirstU = BS.FirstUParameter() <= -Precision::Infinite() ? -theMaxParam : BS.FirstUParameter();
636   Standard_Real LastU  = BS.LastUParameter()  >=  Precision::Infinite() ?  theMaxParam : BS.LastUParameter();
637   Standard_Real FirstV = BS.FirstVParameter() <= -Precision::Infinite() ? -theMaxParam : BS.FirstVParameter();
638   Standard_Real LastV  = BS.LastVParameter()  >=  Precision::Infinite() ?  theMaxParam : BS.LastVParameter();
639
640   if (BS.GetType() == GeomAbs_Plane)
641   {
642     gp_Pnt pcur;
643     Handle(TColgp_HArray1OfPnt) P = new TColgp_HArray1OfPnt (1, 5);
644     BS.D0 (FirstU, FirstV, pcur);
645     P->SetValue (1, pcur);
646     BS.D0 (LastU, FirstV, pcur);
647     P->SetValue (2, pcur);
648     BS.D0 (LastU, LastV, pcur);
649     P->SetValue (3, pcur);
650     BS.D0 (FirstU, LastV, pcur);
651     P->SetValue (4, pcur);
652     P->SetValue (5, P->Value (1));
653     // if the plane is "infinite", it is sensitive only on the border limited by MaxParam
654     if (FirstU == -theMaxParam && LastU == theMaxParam && FirstV == -theMaxParam && LastV == theMaxParam)
655     {
656       theSensitiveList.Append (new Select3D_SensitiveFace (theOwner, P, Select3D_TOS_BOUNDARY));
657     }
658     else
659     {
660       Select3D_TypeOfSensitivity TS = theInteriorFlag ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
661       theSensitiveList.Append (new Select3D_SensitiveFace (theOwner, P, TS));
662     }
663     return Standard_True;
664   }
665
666   // This is construction of a sevsitive polygon from the exterior contour of the face...
667   // It is not good at all, but...
668   TopoDS_Wire aWire;
669   TopExp_Explorer anExpWiresInFace (theFace, TopAbs_WIRE);
670   if (anExpWiresInFace.More())
671   {
672     // believing that this is the first... to be seen
673     aWire = TopoDS::Wire (anExpWiresInFace.Current());
674   }
675   if (aWire.IsNull())
676   {
677     return Standard_False;
678   }
679
680   TColgp_SequenceOfPnt WirePoints;
681   Standard_Boolean FirstExp = Standard_True;
682   Standard_Real wf, wl;
683   BRepAdaptor_Curve cu3d;
684   for (BRepTools_WireExplorer aWireExplorer (aWire);
685        aWireExplorer.More(); aWireExplorer.Next())
686   {
687     cu3d.Initialize (aWireExplorer.Current());
688     BRep_Tool::Range (aWireExplorer.Current(), wf, wl);
689     if (Abs (wf - wl) <= Precision::Confusion())
690     {
691     #ifdef OCCT_DEBUG
692       cout<<" StdSelect_BRepSelectionTool : Curve where ufirst = ulast ...."<<endl;
693     #endif
694     }
695     else
696     {
697       if (FirstExp)
698       {
699         if (aWireExplorer.Orientation() == TopAbs_FORWARD)
700         {
701           WirePoints.Append (cu3d.Value (wf));
702         }
703         else
704         {
705           WirePoints.Append (cu3d.Value (wl));
706         }
707         FirstExp = Standard_False;
708       }
709
710       switch (cu3d.GetType())
711       {
712         case GeomAbs_Line:
713         {
714           WirePoints.Append (cu3d.Value ((aWireExplorer.Orientation() == TopAbs_FORWARD) ? wl : wf));
715           break;
716         }
717         case GeomAbs_Circle:
718         {
719           if (2 * M_PI - Abs (wl - wf) <= Precision::Confusion())
720           {
721             if (BS.GetType() == GeomAbs_Cylinder ||
722                 BS.GetType() == GeomAbs_Torus ||
723                 BS.GetType() == GeomAbs_Cone  ||
724                 BS.GetType() == GeomAbs_BSplineSurface) // beuurkk pour l'instant...
725             {
726               Standard_Real ff = wf ,ll = wl;
727               Standard_Real dw =(Max (wf, wl) - Min (wf, wl)) / (Standard_Real )Max (2, NbPOnEdge - 1);
728               if (aWireExplorer.Orientation() == TopAbs_FORWARD)
729               {
730                 for (Standard_Real wc = wf + dw; wc <= wl; wc += dw)
731                 {
732                   WirePoints.Append (cu3d.Value (wc));
733                 }
734               }
735               else if (aWireExplorer.Orientation() == TopAbs_REVERSED)
736               {
737                 for (Standard_Real wc = ll - dw; wc >= ff; wc -= dw)
738                 {
739                   WirePoints.Append (cu3d.Value (wc));
740                 }
741               }
742             }
743             else
744             {
745               if (cu3d.Circle().Radius() <= Precision::Confusion())
746               {
747                 theSensitiveList.Append (new Select3D_SensitivePoint (theOwner, cu3d.Circle().Location()));
748               }
749               else
750               {
751                 theSensitiveList.Append (new Select3D_SensitiveCircle (theOwner, new Geom_Circle (cu3d.Circle()), theInteriorFlag, 16));
752               }
753             }
754           }
755           else
756           {
757             Standard_Real ff = wf, ll = wl;
758             Standard_Real dw = (Max (wf, wl) - Min (wf, wl)) / (Standard_Real )Max (2, NbPOnEdge - 1);
759             if (aWireExplorer.Orientation() == TopAbs_FORWARD)
760             {
761               for (Standard_Real wc = wf + dw; wc <= wl; wc += dw)
762               {
763                 WirePoints.Append (cu3d.Value (wc));
764               }
765             }
766             else if (aWireExplorer.Orientation() == TopAbs_REVERSED)
767             {
768               for (Standard_Real wc = ll - dw; wc >= ff; wc -= dw)
769               {
770                 WirePoints.Append (cu3d.Value (wc));
771               }
772             }
773           }
774           break;
775         }
776         default:
777         {
778           Standard_Real ff = wf, ll = wl;
779           Standard_Real dw = (Max (wf, wl) - Min (wf, wl)) / (Standard_Real )Max (2, NbPOnEdge - 1);
780           if (aWireExplorer.Orientation()==TopAbs_FORWARD)
781           {
782             for (Standard_Real wc = wf + dw; wc <= wl; wc += dw)
783             {
784               WirePoints.Append (cu3d.Value (wc));
785             }
786           }
787           else if (aWireExplorer.Orientation() == TopAbs_REVERSED)
788           {
789             for (Standard_Real wc = ll - dw; wc >= ff; wc -= dw)
790             {
791               WirePoints.Append (cu3d.Value (wc));
792             }
793           }
794         }
795       }
796     }
797   }
798   Standard_Integer ArrayPosition = WirePoints.Length();
799
800   Handle(TColgp_HArray1OfPnt) facepoints = new TColgp_HArray1OfPnt (1, ArrayPosition);
801   for (Standard_Integer I = 1; I <= ArrayPosition; ++I)
802   {
803     facepoints->SetValue (I, WirePoints.Value(I));
804   }
805
806   if ((facepoints->Array1()).Length() > 1)
807   { //1 if only one circular edge
808     Select3D_TypeOfSensitivity TS = theInteriorFlag ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
809     theSensitiveList.Append (new Select3D_SensitiveFace (theOwner, facepoints, TS));
810   }
811   return Standard_True;
812 }