f91311dc7b83bc6cbbea0ff3b7a574444e14572c
[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   Handle(StdSelect_BRepOwner) aBrepOwner;
71   switch (theType)
72   {
73     case TopAbs_VERTEX:
74     case TopAbs_EDGE:
75     case TopAbs_WIRE:
76     case TopAbs_FACE:
77     case TopAbs_SHELL:
78     case TopAbs_SOLID:
79     case TopAbs_COMPSOLID:
80     {
81       TopTools_IndexedMapOfShape aSubShapes;
82       TopExp::MapShapes (theShape, theType, aSubShapes);
83
84       Standard_Boolean isComesFromDecomposition = !((aSubShapes.Extent() == 1) && (theShape == aSubShapes (1)));
85       for (Standard_Integer aShIndex = 1; aShIndex <= aSubShapes.Extent(); ++aShIndex)
86       {
87         const TopoDS_Shape& aSubShape = aSubShapes (aShIndex);
88         aBrepOwner = new StdSelect_BRepOwner (aSubShape, aPriority, isComesFromDecomposition);
89         ComputeSensitive (aSubShape, aBrepOwner,
90                           theSelection,
91                           theDeflection,
92                           theDeviationAngle,
93                           theNbPOnEdge,
94                           theMaxParam,
95                           isAutoTriangulation);
96       }
97       break;
98     }
99     default:
100     {
101       aBrepOwner = new StdSelect_BRepOwner (theShape, aPriority);
102       ComputeSensitive (theShape, aBrepOwner,
103                         theSelection,
104                         theDeflection,
105                         theDeviationAngle,
106                         theNbPOnEdge,
107                         theMaxParam,
108                         isAutoTriangulation);
109     }
110   }
111 }
112
113 //==================================================
114 // Function: Load
115 // Purpose :
116 //==================================================
117 void StdSelect_BRepSelectionTool
118 ::Load (const Handle(SelectMgr_Selection)& theSelection,
119         const Handle(SelectMgr_SelectableObject)& theSelectableObj,
120         const TopoDS_Shape& theShape,
121         const TopAbs_ShapeEnum theType,
122         const Standard_Real theDeflection,
123         const Standard_Real theDeviationAngle,
124         const Standard_Boolean isAutoTriangulation,
125         const Standard_Integer thePriority,
126         const Standard_Integer theNbPOnEdge,
127         const Standard_Real theMaxParam)
128 {
129   Load (theSelection,
130         theShape,
131         theType,
132         theDeflection,
133         theDeviationAngle,
134         isAutoTriangulation,
135         thePriority,
136         theNbPOnEdge,
137         theMaxParam);
138
139   // loading of selectables...
140   for (theSelection->Init(); theSelection->More(); theSelection->Next())
141   {
142     Handle(SelectMgr_EntityOwner) anOwner
143       = Handle(SelectMgr_EntityOwner)::DownCast (theSelection->Sensitive()->OwnerId());
144     anOwner->Set (theSelectableObj);
145   }
146 }
147
148 //==================================================
149 // Function: ComputeSensitive
150 // Purpose :
151 //==================================================
152 void StdSelect_BRepSelectionTool
153 ::ComputeSensitive (const TopoDS_Shape& theShape,
154                     const Handle(StdSelect_BRepOwner)& theOwner,
155                     const Handle(SelectMgr_Selection)& theSelection,
156                     const Standard_Real theDeflection,
157                     const Standard_Real theDeviationAngle,
158                     const Standard_Integer theNbPOnEdge,
159                     const Standard_Real theMaxParam,
160                     const Standard_Boolean isAutoTriangulation)
161 {
162   switch (theShape.ShapeType())
163   {
164     case TopAbs_VERTEX:
165     {
166       theSelection->Add (new Select3D_SensitivePoint
167                          (theOwner, BRep_Tool::Pnt (TopoDS::Vertex (theShape))));
168       break;
169     }
170     case TopAbs_EDGE:
171     {
172       Handle(Select3D_SensitiveEntity) aSensitive;
173       GetEdgeSensitive (theShape, theOwner, theSelection,
174                         theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam,
175                         aSensitive);
176       if (!aSensitive.IsNull())
177       {
178         theSelection->Add (aSensitive);
179       }
180       break;
181     }
182     case TopAbs_WIRE:
183     {
184       BRepTools_WireExplorer aWireExp (TopoDS::Wire (theShape));
185       Handle (Select3D_SensitiveEntity) aSensitive;
186       Handle (Select3D_SensitiveWire) aWireSensitive = new Select3D_SensitiveWire (theOwner);
187       theSelection->Add (aWireSensitive);
188       while (aWireExp.More())
189       {
190         GetEdgeSensitive (aWireExp.Current(), theOwner, theSelection,
191                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam,
192                           aSensitive);
193         if (!aSensitive.IsNull())
194         {
195           aWireSensitive->Add (aSensitive);
196         }
197         aWireExp.Next();
198       }
199       break;
200     }
201     case TopAbs_FACE:
202     {
203       const TopoDS_Face& aFace = TopoDS::Face (theShape);
204       Select3D_ListOfSensitive aSensitiveList;
205       GetSensitiveForFace (aFace, theOwner,
206                            aSensitiveList,
207                            isAutoTriangulation, theNbPOnEdge, theMaxParam);
208       for (Select3D_ListIteratorOfListOfSensitive aSensIter (aSensitiveList);
209            aSensIter.More(); aSensIter.Next())
210       {
211         theSelection->Add (aSensIter.Value());
212       }
213       break;
214     }
215     case TopAbs_SHELL:
216     {
217       Handle(Select3D_SensitiveGroup) aSensitiveGroup = new Select3D_SensitiveGroup (theOwner);
218       Select3D_ListOfSensitive aSensitiveList;
219       TopTools_IndexedMapOfShape aSubfacesMap;
220       TopExp::MapShapes (theShape, TopAbs_FACE, aSubfacesMap);
221       for (Standard_Integer aShIndex = 1; aShIndex <= aSubfacesMap.Extent(); ++aShIndex)
222       {
223         GetSensitiveForFace (TopoDS::Face (aSubfacesMap (aShIndex)), theOwner,
224                              aSensitiveList,
225                              isAutoTriangulation, theNbPOnEdge, theMaxParam);
226       }
227       if (!aSensitiveList.IsEmpty())
228       {
229         aSensitiveGroup->Add (aSensitiveList);
230         theSelection->Add (aSensitiveGroup);
231       }
232       break;
233     }
234     case TopAbs_SOLID:
235     case TopAbs_COMPSOLID:
236     {
237       TopTools_IndexedMapOfShape aSubfacesMap;
238       TopExp::MapShapes (theShape, TopAbs_FACE, aSubfacesMap);
239       for (Standard_Integer aShIndex = 1; aShIndex <= aSubfacesMap.Extent(); ++aShIndex)
240       {
241         ComputeSensitive (aSubfacesMap (aShIndex), theOwner,
242                           theSelection,
243                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
244       }
245       break;
246     }
247     case TopAbs_COMPOUND:
248     default:
249     {
250       TopExp_Explorer anExp;
251       // sub-vertices
252       for (anExp.Init (theShape, TopAbs_VERTEX, TopAbs_EDGE); anExp.More(); anExp.Next())
253       {
254         ComputeSensitive (anExp.Current(), theOwner,
255                           theSelection,
256                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
257       }
258       // sub-edges
259       for (anExp.Init (theShape, TopAbs_EDGE, TopAbs_FACE); anExp.More(); anExp.Next())
260       {
261         ComputeSensitive (anExp.Current(), theOwner,
262                           theSelection,
263                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
264       }
265       // sub-wires
266       for (anExp.Init (theShape, TopAbs_WIRE, TopAbs_FACE); anExp.More(); anExp.Next())
267       {
268         ComputeSensitive (anExp.Current(), theOwner,
269                           theSelection,
270                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
271       }
272
273       // sub-faces
274       TopTools_IndexedMapOfShape aSubfacesMap;
275       TopExp::MapShapes (theShape, TopAbs_FACE, aSubfacesMap);
276       for (Standard_Integer aShIndex = 1; aShIndex <= aSubfacesMap.Extent(); ++aShIndex)
277       {
278         ComputeSensitive (aSubfacesMap (aShIndex), theOwner,
279                           theSelection,
280                           theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
281       }
282     }
283   }
284 }
285
286 //==================================================
287 // Function: GetPointsFromPolygon
288 // Purpose :
289 //==================================================
290 static Handle(TColgp_HArray1OfPnt) GetPointsFromPolygon (const TopoDS_Edge& theEdge,
291                                                          const Standard_Real theDeflection)
292 {
293   Handle(TColgp_HArray1OfPnt) aResultPoints;
294
295   Standard_Real fi, la;
296   Handle(Geom_Curve) CC3d = BRep_Tool::Curve (theEdge, fi, la);
297
298   TopLoc_Location aLocation;
299   Handle(Poly_Polygon3D) aPolygon = BRep_Tool::Polygon3D (theEdge, aLocation);
300   if (!aPolygon.IsNull())
301   {
302     Standard_Boolean isOK = aPolygon->Deflection() <= theDeflection;
303     isOK = isOK || (CC3d.IsNull());
304     if (isOK)
305     {
306       const TColgp_Array1OfPnt& aNodes = aPolygon->Nodes();
307       aResultPoints = new TColgp_HArray1OfPnt (1, aNodes.Length());
308       if (aLocation.IsIdentity())
309       {
310         for (Standard_Integer aNodeId (aNodes.Lower()), aPntId (1); aNodeId <= aNodes.Upper(); ++aNodeId, ++aPntId)
311         {
312           aResultPoints->SetValue (aPntId, aNodes.Value (aNodeId));
313         }
314       }
315       else
316       {
317         for (Standard_Integer aNodeId (aNodes.Lower()), aPntId (1); aNodeId <= aNodes.Upper(); ++aNodeId, ++aPntId)
318         {
319           aResultPoints->SetValue (aPntId, aNodes.Value (aNodeId).Transformed (aLocation));
320         }
321       }
322       return aResultPoints;
323     }
324   }
325
326   Handle(Poly_Triangulation) aTriangulation;
327   Handle(Poly_PolygonOnTriangulation) anHIndices;
328   BRep_Tool::PolygonOnTriangulation (theEdge, anHIndices, aTriangulation, aLocation);
329   if (!anHIndices.IsNull())
330   {
331     Standard_Boolean isOK = anHIndices->Deflection() <= theDeflection;
332     isOK = isOK || (CC3d.IsNull());
333     if (isOK)
334     {
335       const TColStd_Array1OfInteger& anIndices = anHIndices->Nodes();
336       const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
337
338       aResultPoints = new TColgp_HArray1OfPnt (1, anIndices.Length());
339
340       if (aLocation.IsIdentity())
341       {
342         for (Standard_Integer anIndex (anIndices.Lower()), aPntId (1); anIndex <= anIndices.Upper(); ++anIndex, ++aPntId)
343         {
344           aResultPoints->SetValue (aPntId, aNodes (anIndices (anIndex)));
345         }
346       }
347       else
348       {
349         for (Standard_Integer anIndex (anIndices.Lower()), aPntId (1); anIndex <= anIndices.Upper(); ++anIndex, ++aPntId)
350         {
351           aResultPoints->SetValue (aPntId, aNodes (anIndices (anIndex)).Transformed (aLocation));
352         }
353       }
354       return aResultPoints;
355     }
356   }
357   return aResultPoints;
358 }
359
360 //==================================================
361 // Function: FindLimits
362 // Purpose :
363 //==================================================
364 static Standard_Boolean FindLimits (const Adaptor3d_Curve& theCurve,
365                                     const Standard_Real    theLimit,
366                                           Standard_Real&   theFirst,
367                                           Standard_Real&   theLast)
368 {
369   theFirst = theCurve.FirstParameter();
370   theLast  = theCurve.LastParameter();
371   Standard_Boolean isFirstInf = Precision::IsNegativeInfinite (theFirst);
372   Standard_Boolean isLastInf  = Precision::IsPositiveInfinite (theLast);
373   if (isFirstInf || isLastInf)
374   {
375     gp_Pnt aPnt1, aPnt2;
376     Standard_Real aDelta = 1.0;
377     Standard_Integer anIterCount = 0;
378     if (isFirstInf && isLastInf)
379     {
380       do {
381         if (anIterCount++ >= 100000) return Standard_False;
382         aDelta *= 2.0;
383         theFirst = - aDelta;
384         theLast  =   aDelta;
385         theCurve.D0 (theFirst, aPnt1);
386         theCurve.D0 (theLast,  aPnt2);
387       } while (aPnt1.Distance (aPnt2) < theLimit);
388     }
389     else if (isFirstInf)
390     {
391       theCurve.D0 (theLast, aPnt2);
392       do {
393         if (anIterCount++ >= 100000) return Standard_False;
394         aDelta *= 2.0;
395         theFirst = theLast - aDelta;
396         theCurve.D0 (theFirst, aPnt1);
397       } while (aPnt1.Distance (aPnt2) < theLimit);
398     }
399     else if (isLastInf)
400     {
401       theCurve.D0 (theFirst, aPnt1);
402       do {
403         if (anIterCount++ >= 100000) return Standard_False;
404         aDelta *= 2.0;
405         theLast = theFirst + aDelta;
406         theCurve.D0 (theLast, aPnt2);
407       } while (aPnt1.Distance (aPnt2) < theLimit);
408     }
409   }
410   return Standard_True;
411 }
412
413 //=====================================================
414 // Function : GetEdgeSensitive
415 // Purpose  : create a sensitive edge to add it
416 //            in computeselection to "aselection" (case of selection of an edge)
417 //            or to "aSensitiveWire" (case of selection of a wire; in this case,
418 //            the sensitive wire is added to "aselection" )
419 //            odl - for selection by rectangle -
420 //=====================================================
421 void StdSelect_BRepSelectionTool
422 ::GetEdgeSensitive (const TopoDS_Shape& theShape,
423                     const Handle(StdSelect_BRepOwner)& theOwner,
424                     const Handle(SelectMgr_Selection)& theSelection,
425                     const Standard_Real theDeflection,
426                     const Standard_Real theDeviationAngle,
427                     const Standard_Integer theNbPOnEdge,
428                     const Standard_Real theMaxParam,
429                     Handle(Select3D_SensitiveEntity)& theSensitive)
430 {
431   const TopoDS_Edge& anEdge = TopoDS::Edge (theShape);
432   BRepAdaptor_Curve cu3d;
433   try {
434     OCC_CATCH_SIGNALS
435     cu3d.Initialize (anEdge);
436   } catch (Standard_NullObject) {
437     return;
438   }
439
440   // try to get points from existing polygons
441   Handle(TColgp_HArray1OfPnt) aPoints = GetPointsFromPolygon (anEdge, theDeflection);
442   if (!aPoints.IsNull() && aPoints->Length() > 0)
443   {
444     theSensitive = new Select3D_SensitiveCurve (theOwner, aPoints);
445     return;
446   }
447
448   Standard_Real aParamFirst = cu3d.FirstParameter();
449   Standard_Real aParamLast  = cu3d.LastParameter();
450   switch (cu3d.GetType())
451   {
452     case GeomAbs_Line:
453     {
454       BRep_Tool::Range (anEdge, aParamFirst, aParamLast);
455       theSensitive = new Select3D_SensitiveSegment (theOwner,
456                                                     cu3d.Value (aParamFirst),
457                                                     cu3d.Value (aParamLast));
458       break;
459     }
460     case GeomAbs_Circle:
461     {
462       Handle (Geom_Circle) aCircle = new Geom_Circle (cu3d.Circle());
463       if (aCircle->Radius() <= Precision::Confusion())
464       {
465         theSelection->Add (new Select3D_SensitivePoint (theOwner, aCircle->Location()));
466       }
467       else
468       {
469         theSensitive = new Select3D_SensitiveCircle (theOwner, aCircle,
470                                                      aParamFirst, aParamLast, Standard_False, 16);
471       }
472       break;
473     }
474     default:
475     {
476       // reproduce drawing behaviour
477       // TODO: remove copy-paste from StdPrs_Curve and some others...
478       if (FindLimits (cu3d, theMaxParam, aParamFirst, aParamLast))
479       {
480         Standard_Integer aNbIntervals = cu3d.NbIntervals (GeomAbs_C1);
481         TColStd_Array1OfReal anIntervals (1, aNbIntervals + 1);
482         cu3d.Intervals (anIntervals, GeomAbs_C1);
483         Standard_Real aV1, aV2;
484         Standard_Integer aNumberOfPoints;
485         TColgp_SequenceOfPnt aPointsSeq;
486         for (Standard_Integer anIntervalId = 1; anIntervalId <= aNbIntervals; ++anIntervalId)
487         {
488           aV1 = anIntervals (anIntervalId);
489           aV2 = anIntervals (anIntervalId + 1);
490           if (aV2 > aParamFirst && aV1 < aParamLast)
491           {
492             aV1 = Max (aV1, aParamFirst);
493             aV2 = Min (aV2, aParamLast);
494
495             GCPnts_TangentialDeflection anAlgo (cu3d, aV1, aV2, theDeviationAngle, theDeflection);
496             aNumberOfPoints = anAlgo.NbPoints();
497
498             for (Standard_Integer aPntId = 1; aPntId < aNumberOfPoints; ++aPntId)
499             {
500               aPointsSeq.Append (anAlgo.Value (aPntId));
501             }
502             if (aNumberOfPoints > 0 && anIntervalId == aNbIntervals)
503             {
504               aPointsSeq.Append (anAlgo.Value (aNumberOfPoints));
505             }
506           }
507         }
508
509         aPoints = new TColgp_HArray1OfPnt (1, aPointsSeq.Length());
510         for (Standard_Integer aPntId = 1; aPntId <= aPointsSeq.Length(); ++aPntId)
511         {
512           aPoints->SetValue (aPntId, aPointsSeq.Value (aPntId));
513         }
514         theSensitive = new Select3D_SensitiveCurve (theOwner, aPoints);
515         break;
516       }
517
518       // simple subdivisions
519       Standard_Integer nbintervals = 1;
520       if (cu3d.GetType() == GeomAbs_BSplineCurve)
521       {
522         nbintervals = cu3d.NbKnots() - 1;
523         nbintervals = Max (1, nbintervals / 3);
524       }
525
526       Standard_Real aParam;
527       Standard_Integer aPntNb = Max (2, theNbPOnEdge * nbintervals);
528       Standard_Real aParamDelta = (aParamLast - aParamFirst) / (aPntNb - 1);
529       Handle(TColgp_HArray1OfPnt) aPointArray = new TColgp_HArray1OfPnt (1, aPntNb);
530       for (Standard_Integer aPntId = 1; aPntId <= aPntNb; ++aPntId)
531       {
532         aParam = aParamFirst + aParamDelta * (aPntId - 1);
533         aPointArray->SetValue (aPntId, cu3d.Value (aParam));
534       }
535       theSensitive = new Select3D_SensitiveCurve (theOwner, aPointArray);
536     }
537     break;
538   }
539 }
540
541 //=====================================================
542 // Function : GetStandardPriority
543 // Purpose  :
544 //=====================================================
545 Standard_Integer StdSelect_BRepSelectionTool::GetStandardPriority (const TopoDS_Shape& theShape,
546                                                                    const TopAbs_ShapeEnum theType)
547 {
548   switch (theType)
549   {
550     case TopAbs_VERTEX: return 8;
551     case TopAbs_EDGE:   return 7;
552     case TopAbs_WIRE:   return 6;
553     case TopAbs_FACE:   return 5;
554     case TopAbs_SHAPE:
555     default:
556       switch (theShape.ShapeType())
557       {
558         case TopAbs_VERTEX:    return 9;
559         case TopAbs_EDGE:      return 8;
560         case TopAbs_WIRE:      return 7;
561         case TopAbs_FACE:      return 6;
562         case TopAbs_SHELL:     return 5;
563         case TopAbs_COMPOUND:
564         case TopAbs_COMPSOLID:
565         case TopAbs_SOLID:
566         case TopAbs_SHAPE:
567         default:
568           return 4;
569       }
570   }
571 }
572
573 //=======================================================================
574 //function : GetSensitiveEntityForFace
575 //purpose  :
576 //=======================================================================
577 Standard_Boolean StdSelect_BRepSelectionTool
578 ::GetSensitiveForFace (const TopoDS_Face& theFace,
579                        const Handle(StdSelect_BRepOwner)& theOwner,
580                        Select3D_ListOfSensitive& theSensitiveList,
581                        const Standard_Boolean theAutoTriangulation,
582                        const Standard_Integer NbPOnEdge,
583                        const Standard_Real    theMaxParam,
584                        const Standard_Boolean theInteriorFlag)
585 {
586   // check if there is triangulation of the face...
587   TopLoc_Location aLoc;
588   Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (theFace, aLoc);
589   if (aTriangulation.IsNull() && theAutoTriangulation)
590   {
591     Standard_Real aDefaultDefl = 0.2;
592     Standard_Real aDefaultAng  = 30 * PI / 180.0;
593     BRepMesh_IncrementalMesh (theFace, aDefaultDefl, Standard_True, aDefaultAng);
594     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 }