Commit | Line | Data |
---|---|---|
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 | 73 | void 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 | 104 | void 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 | 168 | void 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 | 201 | void 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 | 325 | static 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 | //================================================== | |
384 | static 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 | 437 | void 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 | //======================================================================= | |
568 | static 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 | //======================================================================= | |
582 | static 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 | 619 | Standard_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 | //======================================================================= | |
932 | Standard_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 | } |