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