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