0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / StdSelect / StdSelect_BRepSelectionTool.cxx
CommitLineData
b311480e 1// Created on: 1995-03-14
2// Created by: Robert COUBLANC
3// Copyright (c) 1995-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
bbf32d01 16
f838dac4 17#include <StdSelect_BRepSelectionTool.hxx>
42cf5bc1 18
42cf5bc1 19#include <BRep_Tool.hxx>
7fd59977 20#include <BRepAdaptor_Curve.hxx>
21#include <BRepAdaptor_Surface.hxx>
42cf5bc1 22#include <BRepMesh_IncrementalMesh.hxx>
23#include <BRepTools.hxx>
24#include <BRepTools_WireExplorer.hxx>
25#include <GCPnts_TangentialDeflection.hxx>
42cf5bc1 26#include <GeomAbs_SurfaceType.hxx>
9dd8af26 27#include <Geom_ConicalSurface.hxx>
28#include <Geom_CylindricalSurface.hxx>
29#include <Geom_Plane.hxx>
503374ad 30#include <Geom_SphericalSurface.hxx>
42cf5bc1 31#include <gp_Circ.hxx>
42cf5bc1 32#include <Poly_Polygon3D.hxx>
33#include <Poly_PolygonOnTriangulation.hxx>
34#include <Poly_Triangulation.hxx>
35#include <Precision.hxx>
7fd59977 36#include <Select3D_SensitiveCircle.hxx>
37#include <Select3D_SensitiveCurve.hxx>
9dd8af26 38#include <Select3D_SensitiveCylinder.hxx>
42cf5bc1 39#include <Select3D_SensitiveEntity.hxx>
7fd59977 40#include <Select3D_SensitiveFace.hxx>
7fd59977 41#include <Select3D_SensitiveGroup.hxx>
42cf5bc1 42#include <Select3D_SensitivePoint.hxx>
7aaed2ce 43#include <Select3D_SensitivePoly.hxx>
42cf5bc1 44#include <Select3D_SensitiveSegment.hxx>
503374ad 45#include <Select3D_SensitiveSphere.hxx>
42cf5bc1 46#include <Select3D_SensitiveTriangulation.hxx>
47#include <Select3D_SensitiveWire.hxx>
48#include <Select3D_TypeOfSensitivity.hxx>
49#include <SelectMgr_EntityOwner.hxx>
50#include <SelectMgr_SelectableObject.hxx>
f751596e 51#include <SelectMgr_Selection.hxx>
42cf5bc1 52#include <Standard_ErrorHandler.hxx>
53#include <Standard_NullObject.hxx>
54#include <StdSelect_BRepOwner.hxx>
7fd59977 55#include <TColgp_HArray1OfPnt.hxx>
56#include <TColgp_SequenceOfPnt.hxx>
57#include <TColStd_Array1OfReal.hxx>
42cf5bc1 58#include <TopExp.hxx>
59#include <TopExp_Explorer.hxx>
60#include <TopoDS.hxx>
61#include <TopoDS_Face.hxx>
62#include <TopoDS_Shape.hxx>
bbf32d01 63#include <TopoDS_Wire.hxx>
7fd59977 64
f751596e 65#define BVH_PRIMITIVE_LIMIT 800000
66
67//==================================================
114b7bf1 68// function: PreBuildBVH
f751596e 69// purpose : Pre-builds BVH tree for heavyweight
70// sensitive entities with sub-elements
71// amount more than BVH_PRIMITIVE_LIMIT
72//==================================================
114b7bf1 73void StdSelect_BRepSelectionTool::PreBuildBVH (const Handle(SelectMgr_Selection)& theSelection)
f751596e 74{
b5cce1ab 75 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
f751596e 76 {
0ef04197 77 const Handle(Select3D_SensitiveEntity)& aSensitive = aSelEntIter.Value()->BaseSensitive();
f751596e 78 if (aSensitive->NbSubElements() >= BVH_PRIMITIVE_LIMIT)
79 {
80 aSensitive->BVH();
81 }
82
f5b72419 83 if (!aSensitive->IsInstance (STANDARD_TYPE(Select3D_SensitiveGroup)))
f751596e 84 {
f5b72419 85 continue;
86 }
87
88 Handle(Select3D_SensitiveGroup) aGroup = Handle(Select3D_SensitiveGroup)::DownCast (aSensitive);
7f5945d6 89 for (Select3D_IndexedMapOfEntity::Iterator aSubEntitiesIter (aGroup->Entities()); aSubEntitiesIter.More(); aSubEntitiesIter.Next())
f5b72419 90 {
91 const Handle(Select3D_SensitiveEntity)& aSubEntity = aSubEntitiesIter.Value();
92 if (aSubEntity->NbSubElements() >= BVH_PRIMITIVE_LIMIT)
f751596e 93 {
f5b72419 94 aSubEntity->BVH();
f751596e 95 }
96 }
97 }
98}
99
7fd59977 100//==================================================
bbf32d01
K
101// Function: Load
102// Purpose :
103//==================================================
f838dac4 104void StdSelect_BRepSelectionTool::Load (const Handle(SelectMgr_Selection)& theSelection,
105 const TopoDS_Shape& theShape,
106 const TopAbs_ShapeEnum theType,
107 const Standard_Real theDeflection,
108 const Standard_Real theDeviationAngle,
109 const Standard_Boolean isAutoTriangulation,
110 const Standard_Integer thePriority,
111 const Standard_Integer theNbPOnEdge,
112 const Standard_Real theMaxParam)
7fd59977 113{
bbf32d01 114 Standard_Integer aPriority = (thePriority == -1) ? GetStandardPriority (theShape, theType) : thePriority;
29263c94 115 if (isAutoTriangulation
116 && !BRepTools::Triangulation (theShape, Precision::Infinite(), true))
3c34883c 117 {
14434f3e 118 BRepMesh_IncrementalMesh aMesher(theShape, theDeflection, Standard_False, theDeviationAngle);
3c34883c
O
119 }
120
bbf32d01
K
121 Handle(StdSelect_BRepOwner) aBrepOwner;
122 switch (theType)
123 {
124 case TopAbs_VERTEX:
125 case TopAbs_EDGE:
126 case TopAbs_WIRE:
127 case TopAbs_FACE:
128 case TopAbs_SHELL:
129 case TopAbs_SOLID:
130 case TopAbs_COMPSOLID:
7fd59977 131 {
bbf32d01
K
132 TopTools_IndexedMapOfShape aSubShapes;
133 TopExp::MapShapes (theShape, theType, aSubShapes);
134
135 Standard_Boolean isComesFromDecomposition = !((aSubShapes.Extent() == 1) && (theShape == aSubShapes (1)));
136 for (Standard_Integer aShIndex = 1; aShIndex <= aSubShapes.Extent(); ++aShIndex)
137 {
138 const TopoDS_Shape& aSubShape = aSubShapes (aShIndex);
139 aBrepOwner = new StdSelect_BRepOwner (aSubShape, aPriority, isComesFromDecomposition);
140 ComputeSensitive (aSubShape, aBrepOwner,
141 theSelection,
142 theDeflection,
143 theDeviationAngle,
144 theNbPOnEdge,
145 theMaxParam,
146 isAutoTriangulation);
7fd59977 147 }
148 break;
149 }
bbf32d01 150 default:
7fd59977 151 {
bbf32d01
K
152 aBrepOwner = new StdSelect_BRepOwner (theShape, aPriority);
153 ComputeSensitive (theShape, aBrepOwner,
154 theSelection,
155 theDeflection,
156 theDeviationAngle,
157 theNbPOnEdge,
158 theMaxParam,
159 isAutoTriangulation);
7fd59977 160 }
7fd59977 161 }
162}
163
bbf32d01
K
164//==================================================
165// Function: Load
166// Purpose :
167//==================================================
f838dac4 168void StdSelect_BRepSelectionTool::Load (const Handle(SelectMgr_Selection)& theSelection,
169 const Handle(SelectMgr_SelectableObject)& theSelectableObj,
170 const TopoDS_Shape& theShape,
171 const TopAbs_ShapeEnum theType,
172 const Standard_Real theDeflection,
173 const Standard_Real theDeviationAngle,
174 const Standard_Boolean isAutoTriangulation,
175 const Standard_Integer thePriority,
176 const Standard_Integer theNbPOnEdge,
177 const Standard_Real theMaxParam)
7fd59977 178{
bbf32d01
K
179 Load (theSelection,
180 theShape,
181 theType,
7fd59977 182 theDeflection,
183 theDeviationAngle,
bbf32d01
K
184 isAutoTriangulation,
185 thePriority,
186 theNbPOnEdge,
187 theMaxParam);
188
189 // loading of selectables...
b5cce1ab 190 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
bbf32d01 191 {
0ef04197 192 const Handle(SelectMgr_EntityOwner)& anOwner = aSelEntIter.Value()->BaseSensitive()->OwnerId();
193 anOwner->SetSelectable (theSelectableObj);
7fd59977 194 }
195}
196
bbf32d01
K
197//==================================================
198// Function: ComputeSensitive
199// Purpose :
200//==================================================
f838dac4 201void StdSelect_BRepSelectionTool::ComputeSensitive (const TopoDS_Shape& theShape,
202 const Handle(SelectMgr_EntityOwner)& theOwner,
203 const Handle(SelectMgr_Selection)& theSelection,
204 const Standard_Real theDeflection,
205 const Standard_Real theDeviationAngle,
206 const Standard_Integer theNbPOnEdge,
207 const Standard_Real theMaxParam,
208 const Standard_Boolean isAutoTriangulation)
7fd59977 209{
bbf32d01
K
210 switch (theShape.ShapeType())
211 {
212 case TopAbs_VERTEX:
213 {
214 theSelection->Add (new Select3D_SensitivePoint
215 (theOwner, BRep_Tool::Pnt (TopoDS::Vertex (theShape))));
7fd59977 216 break;
217 }
bbf32d01
K
218 case TopAbs_EDGE:
219 {
220 Handle(Select3D_SensitiveEntity) aSensitive;
221 GetEdgeSensitive (theShape, theOwner, theSelection,
222 theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam,
223 aSensitive);
224 if (!aSensitive.IsNull())
225 {
226 theSelection->Add (aSensitive);
227 }
7fd59977 228 break;
229 }
bbf32d01 230 case TopAbs_WIRE:
7fd59977 231 {
bbf32d01 232 BRepTools_WireExplorer aWireExp (TopoDS::Wire (theShape));
7fd59977 233 Handle (Select3D_SensitiveEntity) aSensitive;
bbf32d01
K
234 Handle (Select3D_SensitiveWire) aWireSensitive = new Select3D_SensitiveWire (theOwner);
235 theSelection->Add (aWireSensitive);
236 while (aWireExp.More())
237 {
238 GetEdgeSensitive (aWireExp.Current(), theOwner, theSelection,
239 theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam,
240 aSensitive);
241 if (!aSensitive.IsNull())
242 {
243 aWireSensitive->Add (aSensitive);
244 }
245 aWireExp.Next();
7fd59977 246 }
247 break;
248 }
bbf32d01 249 case TopAbs_FACE:
7fd59977 250 {
bbf32d01 251 const TopoDS_Face& aFace = TopoDS::Face (theShape);
7aaed2ce 252
f751596e 253 Select3D_EntitySequence aSensitiveList;
bbf32d01
K
254 GetSensitiveForFace (aFace, theOwner,
255 aSensitiveList,
256 isAutoTriangulation, theNbPOnEdge, theMaxParam);
f751596e 257 for (Select3D_EntitySequenceIter aSensIter (aSensitiveList);
bbf32d01
K
258 aSensIter.More(); aSensIter.Next())
259 {
260 theSelection->Add (aSensIter.Value());
261 }
7fd59977 262 break;
263 }
bbf32d01 264 case TopAbs_SHELL:
bbf32d01
K
265 case TopAbs_SOLID:
266 case TopAbs_COMPSOLID:
7fd59977 267 {
bbf32d01
K
268 TopTools_IndexedMapOfShape aSubfacesMap;
269 TopExp::MapShapes (theShape, TopAbs_FACE, aSubfacesMap);
9dd8af26 270
7aaed2ce 271 if (!GetSensitiveForCylinder (aSubfacesMap, theOwner, theSelection))
9dd8af26 272 {
7aaed2ce 273 for (Standard_Integer aShIndex = 1; aShIndex <= aSubfacesMap.Extent(); ++aShIndex)
9dd8af26 274 {
7aaed2ce 275 ComputeSensitive (aSubfacesMap.FindKey (aShIndex), theOwner,
276 theSelection,
277 theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
9dd8af26 278 }
bbf32d01 279 }
7fd59977 280 break;
281 }
bbf32d01
K
282 case TopAbs_COMPOUND:
283 default:
7fd59977 284 {
bbf32d01
K
285 TopExp_Explorer anExp;
286 // sub-vertices
287 for (anExp.Init (theShape, TopAbs_VERTEX, TopAbs_EDGE); anExp.More(); anExp.Next())
288 {
289 ComputeSensitive (anExp.Current(), theOwner,
290 theSelection,
291 theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
292 }
293 // sub-edges
294 for (anExp.Init (theShape, TopAbs_EDGE, TopAbs_FACE); anExp.More(); anExp.Next())
295 {
296 ComputeSensitive (anExp.Current(), theOwner,
297 theSelection,
298 theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
299 }
300 // sub-wires
301 for (anExp.Init (theShape, TopAbs_WIRE, TopAbs_FACE); anExp.More(); anExp.Next())
302 {
303 ComputeSensitive (anExp.Current(), theOwner,
304 theSelection,
305 theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
306 }
7fd59977 307
bbf32d01
K
308 // sub-faces
309 TopTools_IndexedMapOfShape aSubfacesMap;
310 TopExp::MapShapes (theShape, TopAbs_FACE, aSubfacesMap);
311 for (Standard_Integer aShIndex = 1; aShIndex <= aSubfacesMap.Extent(); ++aShIndex)
312 {
313 ComputeSensitive (aSubfacesMap (aShIndex), theOwner,
314 theSelection,
315 theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
316 }
317 }
318 }
7fd59977 319}
320
bbf32d01
K
321//==================================================
322// Function: GetPointsFromPolygon
323// Purpose :
324//==================================================
36679076 325static Handle(TColgp_HArray1OfPnt) GetPointsFromPolygon (const TopoDS_Edge& theEdge)
7fd59977 326{
327 Handle(TColgp_HArray1OfPnt) aResultPoints;
328
7fd59977 329 TopLoc_Location aLocation;
330 Handle(Poly_Polygon3D) aPolygon = BRep_Tool::Polygon3D (theEdge, aLocation);
331 if (!aPolygon.IsNull())
332 {
36679076 333 const TColgp_Array1OfPnt& aNodes = aPolygon->Nodes();
334 aResultPoints = new TColgp_HArray1OfPnt (1, aNodes.Length());
335 if (aLocation.IsIdentity())
7fd59977 336 {
36679076 337 for (Standard_Integer aNodeId (aNodes.Lower()), aPntId (1); aNodeId <= aNodes.Upper(); ++aNodeId, ++aPntId)
7fd59977 338 {
36679076 339 aResultPoints->SetValue (aPntId, aNodes.Value (aNodeId));
7fd59977 340 }
36679076 341 }
342 else
343 {
344 for (Standard_Integer aNodeId (aNodes.Lower()), aPntId (1); aNodeId <= aNodes.Upper(); ++aNodeId, ++aPntId)
7fd59977 345 {
36679076 346 aResultPoints->SetValue (aPntId, aNodes.Value (aNodeId).Transformed (aLocation));
7fd59977 347 }
7fd59977 348 }
36679076 349 return aResultPoints;
7fd59977 350 }
351
352 Handle(Poly_Triangulation) aTriangulation;
353 Handle(Poly_PolygonOnTriangulation) anHIndices;
354 BRep_Tool::PolygonOnTriangulation (theEdge, anHIndices, aTriangulation, aLocation);
355 if (!anHIndices.IsNull())
356 {
36679076 357 const TColStd_Array1OfInteger& anIndices = anHIndices->Nodes();
7fd59977 358
36679076 359 aResultPoints = new TColgp_HArray1OfPnt (1, anIndices.Length());
7fd59977 360
36679076 361 if (aLocation.IsIdentity())
362 {
363 for (Standard_Integer anIndex (anIndices.Lower()), aPntId (1); anIndex <= anIndices.Upper(); ++anIndex, ++aPntId)
7fd59977 364 {
a8b605eb 365 aResultPoints->SetValue (aPntId, aTriangulation->Node (anIndices[anIndex]));
7fd59977 366 }
36679076 367 }
368 else
369 {
370 for (Standard_Integer anIndex (anIndices.Lower()), aPntId (1); anIndex <= anIndices.Upper(); ++anIndex, ++aPntId)
7fd59977 371 {
a8b605eb 372 aResultPoints->SetValue (aPntId, aTriangulation->Node (anIndices[anIndex]).Transformed (aLocation));
7fd59977 373 }
7fd59977 374 }
36679076 375 return aResultPoints;
7fd59977 376 }
377 return aResultPoints;
378}
379
bbf32d01
K
380//==================================================
381// Function: FindLimits
382// Purpose :
383//==================================================
384static Standard_Boolean FindLimits (const Adaptor3d_Curve& theCurve,
385 const Standard_Real theLimit,
386 Standard_Real& theFirst,
387 Standard_Real& theLast)
7fd59977 388{
bbf32d01
K
389 theFirst = theCurve.FirstParameter();
390 theLast = theCurve.LastParameter();
391 Standard_Boolean isFirstInf = Precision::IsNegativeInfinite (theFirst);
392 Standard_Boolean isLastInf = Precision::IsPositiveInfinite (theLast);
393 if (isFirstInf || isLastInf)
394 {
395 gp_Pnt aPnt1, aPnt2;
396 Standard_Real aDelta = 1.0;
397 Standard_Integer anIterCount = 0;
398 if (isFirstInf && isLastInf)
399 {
7fd59977 400 do {
bbf32d01
K
401 if (anIterCount++ >= 100000) return Standard_False;
402 aDelta *= 2.0;
403 theFirst = - aDelta;
404 theLast = aDelta;
405 theCurve.D0 (theFirst, aPnt1);
406 theCurve.D0 (theLast, aPnt2);
407 } while (aPnt1.Distance (aPnt2) < theLimit);
7fd59977 408 }
bbf32d01
K
409 else if (isFirstInf)
410 {
411 theCurve.D0 (theLast, aPnt2);
7fd59977 412 do {
bbf32d01
K
413 if (anIterCount++ >= 100000) return Standard_False;
414 aDelta *= 2.0;
415 theFirst = theLast - aDelta;
416 theCurve.D0 (theFirst, aPnt1);
417 } while (aPnt1.Distance (aPnt2) < theLimit);
7fd59977 418 }
bbf32d01
K
419 else if (isLastInf)
420 {
421 theCurve.D0 (theFirst, aPnt1);
7fd59977 422 do {
bbf32d01
K
423 if (anIterCount++ >= 100000) return Standard_False;
424 aDelta *= 2.0;
425 theLast = theFirst + aDelta;
426 theCurve.D0 (theLast, aPnt2);
427 } while (aPnt1.Distance (aPnt2) < theLimit);
7fd59977 428 }
bbf32d01 429 }
7fd59977 430 return Standard_True;
431}
432
433//=====================================================
434// Function : GetEdgeSensitive
f838dac4 435// Purpose :
bbf32d01 436//=====================================================
f838dac4 437void StdSelect_BRepSelectionTool::GetEdgeSensitive (const TopoDS_Shape& theShape,
438 const Handle(SelectMgr_EntityOwner)& theOwner,
439 const Handle(SelectMgr_Selection)& theSelection,
440 const Standard_Real theDeflection,
441 const Standard_Real theDeviationAngle,
442 const Standard_Integer theNbPOnEdge,
443 const Standard_Real theMaxParam,
444 Handle(Select3D_SensitiveEntity)& theSensitive)
7fd59977 445{
bbf32d01 446 const TopoDS_Edge& anEdge = TopoDS::Edge (theShape);
e05d8d90 447 // try to get points from existing polygons
448 Handle(TColgp_HArray1OfPnt) aPoints = GetPointsFromPolygon (anEdge);
449 if (!aPoints.IsNull()
450 && !aPoints->IsEmpty())
451 {
29263c94 452 if (aPoints->Length() == 2)
453 {
454 // don't waste memory, create a segment
455 theSensitive = new Select3D_SensitiveSegment (theOwner, aPoints->First(), aPoints->Last());
456 }
457 else
458 {
459 theSensitive = new Select3D_SensitiveCurve (theOwner, aPoints);
460 }
e05d8d90 461 return;
462 }
463
bbf32d01
K
464 BRepAdaptor_Curve cu3d;
465 try {
466 OCC_CATCH_SIGNALS
467 cu3d.Initialize (anEdge);
a738b534 468 } catch (Standard_NullObject const&) {
bbf32d01
K
469 return;
470 }
7fd59977 471
bbf32d01
K
472 Standard_Real aParamFirst = cu3d.FirstParameter();
473 Standard_Real aParamLast = cu3d.LastParameter();
474 switch (cu3d.GetType())
475 {
476 case GeomAbs_Line:
7fd59977 477 {
bbf32d01
K
478 BRep_Tool::Range (anEdge, aParamFirst, aParamLast);
479 theSensitive = new Select3D_SensitiveSegment (theOwner,
480 cu3d.Value (aParamFirst),
481 cu3d.Value (aParamLast));
7fd59977 482 break;
483 }
bbf32d01 484 case GeomAbs_Circle:
7fd59977 485 {
7f24b768 486 const gp_Circ aCircle = cu3d.Circle();
487 if (aCircle.Radius() <= Precision::Confusion())
bbf32d01 488 {
7f24b768 489 theSelection->Add (new Select3D_SensitivePoint (theOwner, aCircle.Location()));
bbf32d01 490 }
7fd59977 491 else
bbf32d01 492 {
7aaed2ce 493 theSensitive = new Select3D_SensitivePoly (theOwner, aCircle, aParamFirst, aParamLast, Standard_False);
bbf32d01 494 }
7fd59977 495 break;
496 }
bbf32d01 497 default:
7fd59977 498 {
bbf32d01
K
499 // reproduce drawing behaviour
500 // TODO: remove copy-paste from StdPrs_Curve and some others...
501 if (FindLimits (cu3d, theMaxParam, aParamFirst, aParamLast))
7fd59977 502 {
503 Standard_Integer aNbIntervals = cu3d.NbIntervals (GeomAbs_C1);
504 TColStd_Array1OfReal anIntervals (1, aNbIntervals + 1);
505 cu3d.Intervals (anIntervals, GeomAbs_C1);
506 Standard_Real aV1, aV2;
507 Standard_Integer aNumberOfPoints;
508 TColgp_SequenceOfPnt aPointsSeq;
7fd59977 509 for (Standard_Integer anIntervalId = 1; anIntervalId <= aNbIntervals; ++anIntervalId)
510 {
bbf32d01
K
511 aV1 = anIntervals (anIntervalId);
512 aV2 = anIntervals (anIntervalId + 1);
513 if (aV2 > aParamFirst && aV1 < aParamLast)
7fd59977 514 {
bbf32d01
K
515 aV1 = Max (aV1, aParamFirst);
516 aV2 = Min (aV2, aParamLast);
7fd59977 517
518 GCPnts_TangentialDeflection anAlgo (cu3d, aV1, aV2, theDeviationAngle, theDeflection);
519 aNumberOfPoints = anAlgo.NbPoints();
520
bbf32d01 521 for (Standard_Integer aPntId = 1; aPntId < aNumberOfPoints; ++aPntId)
7fd59977 522 {
bbf32d01
K
523 aPointsSeq.Append (anAlgo.Value (aPntId));
524 }
525 if (aNumberOfPoints > 0 && anIntervalId == aNbIntervals)
526 {
527 aPointsSeq.Append (anAlgo.Value (aNumberOfPoints));
7fd59977 528 }
529 }
530 }
531
532 aPoints = new TColgp_HArray1OfPnt (1, aPointsSeq.Length());
533 for (Standard_Integer aPntId = 1; aPntId <= aPointsSeq.Length(); ++aPntId)
534 {
535 aPoints->SetValue (aPntId, aPointsSeq.Value (aPntId));
536 }
bbf32d01 537 theSensitive = new Select3D_SensitiveCurve (theOwner, aPoints);
7fd59977 538 break;
539 }
540
541 // simple subdivisions
542 Standard_Integer nbintervals = 1;
bbf32d01
K
543 if (cu3d.GetType() == GeomAbs_BSplineCurve)
544 {
545 nbintervals = cu3d.NbKnots() - 1;
546 nbintervals = Max (1, nbintervals / 3);
7fd59977 547 }
bbf32d01
K
548
549 Standard_Real aParam;
550 Standard_Integer aPntNb = Max (2, theNbPOnEdge * nbintervals);
551 Standard_Real aParamDelta = (aParamLast - aParamFirst) / (aPntNb - 1);
552 Handle(TColgp_HArray1OfPnt) aPointArray = new TColgp_HArray1OfPnt (1, aPntNb);
553 for (Standard_Integer aPntId = 1; aPntId <= aPntNb; ++aPntId)
554 {
555 aParam = aParamFirst + aParamDelta * (aPntId - 1);
556 aPointArray->SetValue (aPntId, cu3d.Value (aParam));
7fd59977 557 }
bbf32d01 558 theSensitive = new Select3D_SensitiveCurve (theOwner, aPointArray);
7fd59977 559 }
560 break;
561 }
562}
563
7aaed2ce 564//=======================================================================
565//function : getCylinderHeight
566//purpose :
567//=======================================================================
568static Standard_Real getCylinderHeight (const Handle(Poly_Triangulation)& theTriangulation,
569 const TopLoc_Location& theLoc)
570{
571 Bnd_Box aBox;
572 gp_Trsf aScaleTrsf;
573 aScaleTrsf.SetScaleFactor (theLoc.Transformation().ScaleFactor());
574 theTriangulation->MinMax (aBox, aScaleTrsf);
575 return aBox.CornerMax().Z() - aBox.CornerMin().Z();
576}
577
578//=======================================================================
579//function : isCylinderOrCone
580//purpose :
581//=======================================================================
582static Standard_Boolean isCylinderOrCone (const TopoDS_Face& theHollowCylinder, const gp_Pnt& theLocation, gp_Dir& theDirection)
583{
584 Standard_Integer aCirclesNb = 0;
585 Standard_Boolean isCylinder = Standard_False;
586 gp_Pnt aPos;
587
588 TopExp_Explorer anEdgeExp;
589 for (anEdgeExp.Init (theHollowCylinder, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next())
590 {
591 const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeExp.Current());
592 BRepAdaptor_Curve anAdaptor (anEdge);
593
594 if (anAdaptor.GetType() == GeomAbs_Circle
595 && BRep_Tool::IsClosed (anEdge))
596 {
597 aCirclesNb++;
598 isCylinder = Standard_True;
599 if (aCirclesNb == 2)
600 {
601 // Reverse the direction of the cylinder, relevant if the cylinder was created as a prism
602 if (aPos.IsEqual (theLocation, Precision::Confusion()))
603 {
604 theDirection.Reverse();
605 }
606 return Standard_True;
607 }
608 aPos = anAdaptor.Circle().Location().XYZ();
609 }
610 }
611
612 return isCylinder;
613}
614
7fd59977 615//=======================================================================
616//function : GetSensitiveEntityForFace
bbf32d01 617//purpose :
7fd59977 618//=======================================================================
f838dac4 619Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForFace (const TopoDS_Face& theFace,
620 const Handle(SelectMgr_EntityOwner)& theOwner,
621 Select3D_EntitySequence& theSensitiveList,
622 const Standard_Boolean /*theAutoTriangulation*/,
623 const Standard_Integer NbPOnEdge,
624 const Standard_Real theMaxParam,
625 const Standard_Boolean theInteriorFlag)
7fd59977 626{
bbf32d01 627 TopLoc_Location aLoc;
c7ba4578 628 if (Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (theFace, aLoc))
bbf32d01 629 {
503374ad 630 TopLoc_Location aLocSurf;
631 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (theFace, aLocSurf);
632 if (Handle(Geom_SphericalSurface) aGeomSphere = Handle(Geom_SphericalSurface)::DownCast (aSurf))
633 {
634 bool isFullSphere = theFace.NbChildren() == 0;
635 if (theFace.NbChildren() == 1)
636 {
637 const TopoDS_Iterator aWireIter (theFace);
638 const TopoDS_Wire& aWire = TopoDS::Wire (aWireIter.Value());
639 if (aWire.NbChildren() == 4)
640 {
641 Standard_Integer aNbSeamEdges = 0, aNbDegenEdges = 0;
642 for (TopoDS_Iterator anEdgeIter (aWire); anEdgeIter.More(); anEdgeIter.Next())
643 {
644 const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Value());
645 aNbSeamEdges += BRep_Tool::IsClosed (anEdge, theFace);
646 aNbDegenEdges += BRep_Tool::Degenerated (anEdge);
647 }
648 isFullSphere = aNbSeamEdges == 2 && aNbDegenEdges == 2;
649 }
650 }
651 if (isFullSphere)
652 {
653 gp_Sphere aSphere = BRepAdaptor_Surface (theFace).Sphere();
654 Handle(Select3D_SensitiveSphere) aSensSphere = new Select3D_SensitiveSphere (theOwner, aSphere.Position().Axis().Location(), aSphere.Radius());
655 theSensitiveList.Append (aSensSphere);
656 return Standard_True;
657 }
658 }
7aaed2ce 659 else if (Handle(Geom_ConicalSurface) aGeomCone = Handle(Geom_ConicalSurface)::DownCast (aSurf))
660 {
661 gp_Dir aDummyDir;
662 if (isCylinderOrCone (theFace, gp_Pnt(), aDummyDir))
663 {
664 const gp_Cone aCone = BRepAdaptor_Surface (theFace).Cone();
665 const Standard_Real aRad1 = aCone.RefRadius();
666 const Standard_Real aHeight = getCylinderHeight (aTriangulation, aLoc);
667
668 gp_Trsf aTrsf;
669 aTrsf.SetTransformation (aCone.Position(), gp::XOY());
670
671 Standard_Real aRad2;
672 if (aRad1 == 0.0)
673 {
674 aRad2 = Tan (aCone.SemiAngle()) * aHeight;
675 }
676 else
677 {
678 const Standard_Real aTriangleHeight = (aCone.SemiAngle() > 0.0)
679 ? aRad1 / Tan (aCone.SemiAngle())
680 : aRad1 / Tan (Abs (aCone.SemiAngle())) - aHeight;
681 aRad2 = (aCone.SemiAngle() > 0.0)
682 ? aRad1 * (aTriangleHeight + aHeight) / aTriangleHeight
683 : aRad1 * aTriangleHeight / (aTriangleHeight + aHeight);
684 }
685
686 Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf, true);
687 theSensitiveList.Append (aSensSCyl);
688 return Standard_True;
689 }
690 }
691 else if (Handle(Geom_CylindricalSurface) aGeomCyl = Handle(Geom_CylindricalSurface)::DownCast (aSurf))
692 {
693 const gp_Cylinder aCyl = BRepAdaptor_Surface (theFace).Cylinder();
694 gp_Ax3 aPos = aCyl.Position();
695 gp_Dir aDirection = aPos.Direction();
696
697 if (isCylinderOrCone (theFace, aPos.Location(), aDirection))
698 {
699 const Standard_Real aRad = aCyl.Radius();
700 const Standard_Real aHeight = getCylinderHeight (aTriangulation, aLoc);
701
702 gp_Trsf aTrsf;
703 aPos.SetDirection (aDirection);
704 aTrsf.SetTransformation (aPos, gp::XOY());
705
706 Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad, aRad, aHeight, aTrsf, true);
707 theSensitiveList.Append (aSensSCyl);
708 return Standard_True;
709 }
710 }
711 else if (Handle(Geom_Plane) aGeomPlane = Handle(Geom_Plane)::DownCast (aSurf))
712 {
713 TopTools_IndexedMapOfShape aSubfacesMap;
714 TopExp::MapShapes (theFace, TopAbs_EDGE, aSubfacesMap);
715 if (aSubfacesMap.Extent() == 1)
716 {
717 const TopoDS_Edge& anEdge = TopoDS::Edge (aSubfacesMap.FindKey (1));
718 BRepAdaptor_Curve anAdaptor (anEdge);
719 if (anAdaptor.GetType() == GeomAbs_Circle
720 && BRep_Tool::IsClosed (anEdge))
721 {
722 Handle(Select3D_SensitiveCircle) aSensSCyl = new Select3D_SensitiveCircle (theOwner, anAdaptor.Circle(), theInteriorFlag);
723 theSensitiveList.Append (aSensSCyl);
724 return Standard_True;
725 }
726 }
727 }
728
bbf32d01
K
729 Handle(Select3D_SensitiveTriangulation) STG = new Select3D_SensitiveTriangulation (theOwner, aTriangulation, aLoc, theInteriorFlag);
730 theSensitiveList.Append (STG);
7fd59977 731 return Standard_True;
732 }
733
81bba717 734 // for faces with triangulation bugs or without autotriangulation ....
735 // very ugly and should not even exist ...
c7ba4578 736 BRepAdaptor_Surface BS (theFace);
bbf32d01
K
737 if (BS.GetType() == GeomAbs_Plane)
738 {
c7ba4578 739 const Standard_Real aFirstU = BS.FirstUParameter() <= -Precision::Infinite() ? -theMaxParam : BS.FirstUParameter();
740 const Standard_Real aLastU = BS.LastUParameter() >= Precision::Infinite() ? theMaxParam : BS.LastUParameter();
741 const Standard_Real aFirstV = BS.FirstVParameter() <= -Precision::Infinite() ? -theMaxParam : BS.FirstVParameter();
742 const Standard_Real aLastV = BS.LastVParameter() >= Precision::Infinite() ? theMaxParam : BS.LastVParameter();
743 Handle(TColgp_HArray1OfPnt) aPlanePnts = new TColgp_HArray1OfPnt (1, 5);
744 BS.D0 (aFirstU, aFirstV, aPlanePnts->ChangeValue (1));
745 BS.D0 (aLastU, aFirstV, aPlanePnts->ChangeValue (2));
746 BS.D0 (aLastU, aLastV, aPlanePnts->ChangeValue (3));
747 BS.D0 (aFirstU, aLastV, aPlanePnts->ChangeValue (4));
748 aPlanePnts->SetValue (5, aPlanePnts->Value (1));
749
81bba717 750 // if the plane is "infinite", it is sensitive only on the border limited by MaxParam
c7ba4578 751 const bool isInfinite = aFirstU == -theMaxParam
752 && aLastU == theMaxParam
753 && aFirstV == -theMaxParam
754 && aLastV == theMaxParam;
755 theSensitiveList.Append (new Select3D_SensitiveFace (theOwner, aPlanePnts,
756 theInteriorFlag && !isInfinite
757 ? Select3D_TOS_INTERIOR
758 : Select3D_TOS_BOUNDARY));
7fd59977 759 return Standard_True;
760 }
bbf32d01 761
c7ba4578 762 // This is construction of a sensitive polygon from the exterior contour of the face...
81bba717 763 // It is not good at all, but...
7fd59977 764 TopoDS_Wire aWire;
bbf32d01 765 {
c7ba4578 766 TopExp_Explorer anExpWiresInFace (theFace, TopAbs_WIRE);
767 if (anExpWiresInFace.More())
768 {
769 // believing that this is the first... to be seen
770 aWire = TopoDS::Wire (anExpWiresInFace.Current());
771 }
bbf32d01
K
772 }
773 if (aWire.IsNull())
774 {
775 return Standard_False;
776 }
7fd59977 777
c7ba4578 778 TColgp_SequenceOfPnt aWirePoints;
779 Standard_Boolean isFirstExp = Standard_True;
bbf32d01 780 BRepAdaptor_Curve cu3d;
c7ba4578 781 for (BRepTools_WireExplorer aWireExplorer (aWire); aWireExplorer.More(); aWireExplorer.Next())
bbf32d01 782 {
4ba5491a 783 try
784 {
785 OCC_CATCH_SIGNALS
786 cu3d.Initialize (aWireExplorer.Current());
787 }
a738b534 788 catch (Standard_NullObject const&)
4ba5491a 789 {
790 continue;
791 }
792
c7ba4578 793 Standard_Real wf = 0.0, wl = 0.0;
bbf32d01
K
794 BRep_Tool::Range (aWireExplorer.Current(), wf, wl);
795 if (Abs (wf - wl) <= Precision::Confusion())
796 {
0797d9d3 797 #ifdef OCCT_DEBUG
04232180 798 std::cout<<" StdSelect_BRepSelectionTool : Curve where ufirst = ulast ...."<<std::endl;
bbf32d01 799 #endif
c7ba4578 800 continue;
7fd59977 801 }
c7ba4578 802
803 if (isFirstExp)
bbf32d01 804 {
c7ba4578 805 isFirstExp = Standard_False;
806 if (aWireExplorer.Orientation() == TopAbs_FORWARD)
bbf32d01 807 {
c7ba4578 808 aWirePoints.Append (cu3d.Value (wf));
809 }
810 else
811 {
812 aWirePoints.Append (cu3d.Value (wl));
7fd59977 813 }
c7ba4578 814 }
bbf32d01 815
c7ba4578 816 switch (cu3d.GetType())
817 {
818 case GeomAbs_Line:
bbf32d01 819 {
c7ba4578 820 aWirePoints.Append (cu3d.Value ((aWireExplorer.Orientation() == TopAbs_FORWARD) ? wl : wf));
821 break;
822 }
823 case GeomAbs_Circle:
824 {
825 if (2.0 * M_PI - Abs (wl - wf) <= Precision::Confusion())
bbf32d01 826 {
c7ba4578 827 if (BS.GetType() == GeomAbs_Cylinder ||
828 BS.GetType() == GeomAbs_Torus ||
829 BS.GetType() == GeomAbs_Cone ||
830 BS.GetType() == GeomAbs_BSplineSurface) // beuurkk pour l'instant...
bbf32d01 831 {
c7ba4578 832 Standard_Real ff = wf ,ll = wl;
833 Standard_Real dw =(Max (wf, wl) - Min (wf, wl)) / (Standard_Real )Max (2, NbPOnEdge - 1);
834 if (aWireExplorer.Orientation() == TopAbs_FORWARD)
bbf32d01 835 {
c7ba4578 836 for (Standard_Real wc = wf + dw; wc <= wl; wc += dw)
bbf32d01 837 {
c7ba4578 838 aWirePoints.Append (cu3d.Value (wc));
bbf32d01
K
839 }
840 }
c7ba4578 841 else if (aWireExplorer.Orientation() == TopAbs_REVERSED)
bbf32d01 842 {
c7ba4578 843 for (Standard_Real wc = ll - dw; wc >= ff; wc -= dw)
bbf32d01 844 {
c7ba4578 845 aWirePoints.Append (cu3d.Value (wc));
bbf32d01
K
846 }
847 }
848 }
849 else
850 {
c7ba4578 851 if (cu3d.Circle().Radius() <= Precision::Confusion())
bbf32d01 852 {
c7ba4578 853 theSensitiveList.Append (new Select3D_SensitivePoint (theOwner, cu3d.Circle().Location()));
bbf32d01 854 }
c7ba4578 855 else
bbf32d01 856 {
7aaed2ce 857 theSensitiveList.Append (new Select3D_SensitiveCircle (theOwner, cu3d.Circle(), theInteriorFlag));
bbf32d01
K
858 }
859 }
bbf32d01 860 }
c7ba4578 861 else
bbf32d01
K
862 {
863 Standard_Real ff = wf, ll = wl;
864 Standard_Real dw = (Max (wf, wl) - Min (wf, wl)) / (Standard_Real )Max (2, NbPOnEdge - 1);
c7ba4578 865 if (aWireExplorer.Orientation() == TopAbs_FORWARD)
bbf32d01
K
866 {
867 for (Standard_Real wc = wf + dw; wc <= wl; wc += dw)
868 {
c7ba4578 869 aWirePoints.Append (cu3d.Value (wc));
bbf32d01
K
870 }
871 }
872 else if (aWireExplorer.Orientation() == TopAbs_REVERSED)
873 {
874 for (Standard_Real wc = ll - dw; wc >= ff; wc -= dw)
875 {
c7ba4578 876 aWirePoints.Append (cu3d.Value (wc));
bbf32d01
K
877 }
878 }
879 }
c7ba4578 880 break;
881 }
882 default:
883 {
884 Standard_Real ff = wf, ll = wl;
885 Standard_Real dw = (Max (wf, wl) - Min (wf, wl)) / (Standard_Real )Max (2, NbPOnEdge - 1);
886 if (aWireExplorer.Orientation()==TopAbs_FORWARD)
887 {
888 for (Standard_Real wc = wf + dw; wc <= wl; wc += dw)
889 {
890 aWirePoints.Append (cu3d.Value (wc));
891 }
892 }
893 else if (aWireExplorer.Orientation() == TopAbs_REVERSED)
894 {
895 for (Standard_Real wc = ll - dw; wc >= ff; wc -= dw)
896 {
897 aWirePoints.Append (cu3d.Value (wc));
898 }
899 }
7fd59977 900 }
901 }
902 }
bbf32d01 903
c7ba4578 904 Handle(TColgp_HArray1OfPnt) aFacePoints = new TColgp_HArray1OfPnt (1, aWirePoints.Length());
bbf32d01 905 {
c7ba4578 906 Standard_Integer aPntIndex = 1;
907 for (TColgp_SequenceOfPnt::Iterator aPntIter (aWirePoints); aPntIter.More(); aPntIter.Next())
908 {
909 aFacePoints->SetValue (aPntIndex++, aPntIter.Value());
910 }
bbf32d01
K
911 }
912
c7ba4578 913 // 1 if only one circular edge
914 if (aFacePoints->Array1().Length() == 2)
915 {
916 theSensitiveList.Append (new Select3D_SensitiveCurve (theOwner, aFacePoints));
917 }
918 else if (aFacePoints->Array1().Length() > 2)
919 {
920 theSensitiveList.Append (new Select3D_SensitiveFace (theOwner, aFacePoints,
921 theInteriorFlag
922 ? Select3D_TOS_INTERIOR
923 : Select3D_TOS_BOUNDARY));
7fd59977 924 }
925 return Standard_True;
926}
7aaed2ce 927
928//=======================================================================
929//function : GetSensitiveForCylinder
930//purpose :
931//=======================================================================
932Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForCylinder (const TopTools_IndexedMapOfShape& theSubfacesMap,
933 const Handle(SelectMgr_EntityOwner)& theOwner,
934 const Handle(SelectMgr_Selection)& theSelection)
935{
936 if (theSubfacesMap.Extent() == 2) // detect cone
937 {
938 const TopoDS_Face* aFaces[2] =
939 {
940 &TopoDS::Face (theSubfacesMap.FindKey (1)),
941 &TopoDS::Face (theSubfacesMap.FindKey (2))
942 };
943
944 TopLoc_Location aLocSurf[2];
945 const Handle(Geom_Surface)* aSurfaces[2] =
946 {
947 &BRep_Tool::Surface (*aFaces[0], aLocSurf[0]),
948 &BRep_Tool::Surface (*aFaces[1], aLocSurf[1])
949 };
950
951 Standard_Integer aConIndex = 0;
952 Handle(Geom_ConicalSurface) aGeomCone = Handle(Geom_ConicalSurface)::DownCast (*aSurfaces[0]);
953 Handle(Geom_Plane) aGeomPln;
954 if (!aGeomCone.IsNull())
955 {
956 aGeomPln = Handle(Geom_Plane)::DownCast (*aSurfaces[1]);
957 }
958 else
959 {
960 aConIndex = 1;
961 aGeomCone = Handle(Geom_ConicalSurface)::DownCast (*aSurfaces[1]);
962 aGeomPln = Handle(Geom_Plane)::DownCast (*aSurfaces[0]);
963 }
964 if (!aGeomCone.IsNull()
965 && !aGeomPln.IsNull()
966 && aGeomPln->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular()))
967 {
968 const gp_Cone aCone = BRepAdaptor_Surface (*aFaces[aConIndex]).Cone();
969 const Standard_Real aRad1 = aCone.RefRadius();
970 const Standard_Real aHeight = (aRad1 != 0.0)
971 ? aRad1 / Abs (Tan (aCone.SemiAngle()))
972 : aCone.Location().Distance (aGeomPln->Location().Transformed (aLocSurf[aConIndex == 0 ? 1 : 0]));
973 const Standard_Real aRad2 = (aRad1 != 0.0) ? 0.0 : Tan (aCone.SemiAngle()) * aHeight;
974 gp_Trsf aTrsf;
975 aTrsf.SetTransformation (aCone.Position(), gp::XOY());
976 Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf);
977 theSelection->Add (aSensSCyl);
978 return Standard_True;
979 }
980 }
981 if (theSubfacesMap.Extent() == 3) // detect cylinder or truncated cone
982 {
983 const TopoDS_Face* aFaces[3] =
984 {
985 &TopoDS::Face (theSubfacesMap.FindKey (1)),
986 &TopoDS::Face (theSubfacesMap.FindKey (2)),
987 &TopoDS::Face (theSubfacesMap.FindKey (3))
988 };
989
990 TopLoc_Location aLocSurf[3];
991 const Handle(Geom_Surface)* aSurfaces[3] =
992 {
993 &BRep_Tool::Surface (*aFaces[0], aLocSurf[0]),
994 &BRep_Tool::Surface (*aFaces[1], aLocSurf[1]),
995 &BRep_Tool::Surface (*aFaces[2], aLocSurf[2])
996 };
997
998 Standard_Integer aConIndex = -1, aNbPlanes = 0;
999 Handle(Geom_ConicalSurface) aGeomCone;
1000 Handle(Geom_CylindricalSurface) aGeomCyl;
1001 Handle(Geom_Plane) aGeomPlanes[2];
1002 const TopLoc_Location* aGeomPlanesLoc[2];
1003 for (Standard_Integer aSurfIter = 0; aSurfIter < 3; ++aSurfIter)
1004 {
1005 const Handle(Geom_Surface)& aSurf = *aSurfaces[aSurfIter];
1006 if (aConIndex == -1)
1007 {
1008 aGeomCone = Handle (Geom_ConicalSurface)::DownCast (aSurf);
1009 if (!aGeomCone.IsNull())
1010 {
1011 aConIndex = aSurfIter;
1012 continue;
1013 }
1014 aGeomCyl = Handle (Geom_CylindricalSurface)::DownCast (aSurf);
1015 if (!aGeomCyl.IsNull())
1016 {
1017 aConIndex = aSurfIter;
1018 continue;
1019 }
1020 }
1021 if (aNbPlanes < 2)
1022 {
1023 aGeomPlanes[aNbPlanes] = Handle(Geom_Plane)::DownCast (aSurf);
1024 if (!aGeomPlanes[aNbPlanes].IsNull())
1025 {
1026 aGeomPlanesLoc[aNbPlanes] = &aLocSurf[aSurfIter];
1027 ++aNbPlanes;
1028 }
1029 }
1030 }
1031
1032 if (!aGeomCone.IsNull())
1033 {
1034 if (!aGeomPlanes[0].IsNull()
1035 && !aGeomPlanes[1].IsNull()
1036 && aGeomPlanes[0]->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular())
1037 && aGeomPlanes[1]->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular()))
1038 {
1039 const gp_Cone aCone = BRepAdaptor_Surface (*aFaces[aConIndex]).Cone();
1040 const Standard_Real aRad1 = aCone.RefRadius();
1041 const Standard_Real aHeight = aGeomPlanes[0]->Location().Transformed (*aGeomPlanesLoc[0])
1042 .Distance (aGeomPlanes[1]->Location().Transformed (*aGeomPlanesLoc[1]));
1043 gp_Trsf aTrsf;
1044 aTrsf.SetTransformation (aCone.Position(), gp::XOY());
1045 const Standard_Real aTriangleHeight = (aCone.SemiAngle() > 0.0)
1046 ? aRad1 / Tan (aCone.SemiAngle())
1047 : aRad1 / Tan (Abs (aCone.SemiAngle())) - aHeight;
1048 const Standard_Real aRad2 = (aCone.SemiAngle() > 0.0)
1049 ? aRad1 * (aTriangleHeight + aHeight) / aTriangleHeight
1050 : aRad1 * aTriangleHeight / (aTriangleHeight + aHeight);
1051
1052 Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf);
1053 theSelection->Add (aSensSCyl);
1054 return Standard_True;
1055 }
1056 }
1057 else if (!aGeomCyl.IsNull())
1058 {
1059 if (!aGeomPlanes[0].IsNull()
1060 && !aGeomPlanes[1].IsNull()
1061 && aGeomPlanes[0]->Position().Direction().IsParallel (aGeomCyl->Position().Direction(), Precision::Angular())
1062 && aGeomPlanes[1]->Position().Direction().IsParallel (aGeomCyl->Position().Direction(), Precision::Angular()))
1063 {
1064 const gp_Cylinder aCyl = BRepAdaptor_Surface (*aFaces[aConIndex]).Cylinder();
1065 const Standard_Real aRad = aCyl.Radius();
1066 const Standard_Real aHeight = aGeomPlanes[0]->Location().Transformed (*aGeomPlanesLoc[0])
1067 .Distance (aGeomPlanes[1]->Location().Transformed (*aGeomPlanesLoc[1]));
1068
1069 gp_Trsf aTrsf;
1070 gp_Ax3 aPos = aCyl.Position();
1071 if (aGeomPlanes[0]->Position().IsCoplanar (aGeomPlanes[1]->Position(), Precision::Angular(), Precision::Angular()))
1072 {
1073 // cylinders created as a prism have an inverse vector of the cylindrical surface
1074 aPos.SetDirection (aPos.Direction().Reversed());
1075 }
1076 aTrsf.SetTransformation (aPos, gp::XOY());
1077
1078 Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad, aRad, aHeight, aTrsf);
1079 theSelection->Add (aSensSCyl);
1080 return Standard_True;
1081 }
1082 }
1083 }
1084
1085 return Standard_False;
1086}