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