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