1 // Created on: 1996-02-06
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <Select3D_SensitiveCircle.hxx>
20 #include <Precision.hxx>
21 #include <Select3D_SensitiveTriangle.hxx>
23 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveCircle,Select3D_SensitivePoly)
27 static Standard_Integer GetCircleNbPoints (const gp_Circ& theCircle,
28 const Standard_Integer theNbPnts)
30 // Check if number of points is invalid.
31 // In this case myPolyg raises Standard_ConstructionError
32 // exception (look constructor bellow).
36 if (theCircle.Radius() > Precision::Confusion())
37 return 2 * theNbPnts + 1;
39 // The radius is too small and circle degenerates into point
43 //! Definition of circle polyline
44 static void initCircle (Select3D_PointData& thePolygon,
45 const gp_Circ& theCircle,
46 const Standard_Real theU1,
47 const Standard_Real theU2,
48 const Standard_Integer theNbPnts)
50 const Standard_Real aStep = (theU2 - theU1) / theNbPnts;
51 const Standard_Real aRadius = theCircle.Radius();
52 Standard_Integer aPntIdx = 0;
53 Standard_Real aCurU = theU1;
56 for (Standard_Integer anIndex = 1; anIndex <= theNbPnts; ++anIndex, aCurU += aStep)
58 ElCLib::CircleD1 (aCurU, theCircle.Position(), theCircle.Radius(), aP1, aV1);
59 thePolygon.SetPnt (aPntIdx++, aP1);
62 const gp_Pnt aP2 = aP1.XYZ() + aV1.XYZ() * Tan (aStep * 0.5) * aRadius;
63 thePolygon.SetPnt (aPntIdx++, aP2);
65 aP1 = ElCLib::CircleValue (theU2, theCircle.Position(), theCircle.Radius());
66 thePolygon.SetPnt (theNbPnts * 2, aP1);
70 //=======================================================================
71 //function : Select3D_SensitiveCircle (constructor)
72 //purpose : Definition of a sensitive circle
73 //=======================================================================
74 Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectMgr_EntityOwner)& theOwnerId,
75 const gp_Circ& theCircle,
76 const Standard_Boolean theIsFilled,
77 const Standard_Integer theNbPnts)
78 : Select3D_SensitivePoly (theOwnerId, !theIsFilled, GetCircleNbPoints (theCircle, theNbPnts)),
83 mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
84 myCenter3D = theCircle.Position().Location();
85 if (myPolyg.Size() != 1)
87 initCircle (myPolyg, theCircle, myStart, myEnd, theNbPnts);
92 myPolyg.SetPnt (0, theCircle.Position().Location());
95 if (mySensType == Select3D_TOS_BOUNDARY)
97 SetSensitivityFactor (6);
101 //=======================================================================
102 //function : Select3D_SensitiveCircle (constructor)
103 //purpose : Definition of a sensitive arc
104 //=======================================================================
105 Select3D_SensitiveCircle::Select3D_SensitiveCircle (const Handle(SelectMgr_EntityOwner)& theOwnerId,
106 const gp_Circ& theCircle,
107 const Standard_Real theU1,
108 const Standard_Real theU2,
109 const Standard_Boolean theIsFilled,
110 const Standard_Integer theNbPnts)
111 : Select3D_SensitivePoly (theOwnerId, !theIsFilled, GetCircleNbPoints (theCircle, theNbPnts)),
112 myCircle (theCircle),
113 myStart (Min (theU1, theU2)),
114 myEnd (Max (theU1, theU2))
116 mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
117 myCenter3D = theCircle.Position().Location();
118 if (myPolyg.Size() != 1)
120 initCircle (myPolyg, theCircle, myStart, myEnd, theNbPnts);
124 myPolyg.SetPnt (0, theCircle.Position().Location());
127 if (mySensType == Select3D_TOS_BOUNDARY)
129 SetSensitivityFactor (6);
133 //=======================================================================
134 //function : Select3D_SensitiveCircle
136 //=======================================================================
137 Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectMgr_EntityOwner)& theOwnerId,
138 const Handle(TColgp_HArray1OfPnt)& thePnts3d,
139 const Standard_Boolean theIsFilled)
140 : Select3D_SensitivePoly (theOwnerId, thePnts3d, static_cast<Standard_Boolean> (!theIsFilled)),
144 mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
146 if (myPolyg.Size() != 1)
149 myCenter3D = myPolyg.Pnt (0);
151 if (mySensType == Select3D_TOS_BOUNDARY)
153 SetSensitivityFactor (6);
157 //=======================================================================
158 //function : Select3D_SensitiveCircle
160 //=======================================================================
162 Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectMgr_EntityOwner)& theOwnerId,
163 const TColgp_Array1OfPnt& thePnts3d,
164 const Standard_Boolean theIsFilled)
165 : Select3D_SensitivePoly (theOwnerId, thePnts3d, !theIsFilled),
169 mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
171 if (myPolyg.Size() != 1)
174 myCenter3D = myPolyg.Pnt (0);
176 if (mySensType == Select3D_TOS_BOUNDARY)
178 SetSensitivityFactor (6);
182 //=======================================================================
184 // purpose : Builds BVH tree for a circle's edge segments if needed
185 //=======================================================================
186 void Select3D_SensitiveCircle::BVH()
188 if (mySensType == Select3D_TOS_BOUNDARY)
190 Select3D_SensitivePoly::BVH();
194 //=======================================================================
195 // function : Matches
196 // purpose : Checks whether the circle overlaps current selecting volume
197 //=======================================================================
198 Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolumeManager& theMgr,
199 SelectBasics_PickResult& thePickResult)
201 if (mySensType == Select3D_TOS_BOUNDARY)
203 if (!Select3D_SensitivePoly::Matches (theMgr, thePickResult))
205 return Standard_False;
208 else if (mySensType == Select3D_TOS_INTERIOR)
210 Handle(TColgp_HArray1OfPnt) anArrayOfPnt;
211 Points3D (anArrayOfPnt);
212 if (!theMgr.IsOverlapAllowed())
214 if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
216 SelectBasics_PickResult aDummy;
217 return theMgr.Overlaps (anArrayOfPnt, mySensType, aDummy);
219 for (Standard_Integer aPntIdx = anArrayOfPnt->Lower(); aPntIdx <= anArrayOfPnt->Upper(); ++aPntIdx)
221 if (!theMgr.Overlaps (anArrayOfPnt->Value(aPntIdx)))
223 return Standard_False;
226 return Standard_True;
229 if (!theMgr.Overlaps (anArrayOfPnt, Select3D_TOS_INTERIOR, thePickResult))
231 return Standard_False;
233 thePickResult.SetDistToGeomCenter(distanceToCOG(theMgr));
236 return Standard_True;
239 //=======================================================================
240 //function : GetConnected
242 //=======================================================================
244 Handle(Select3D_SensitiveEntity) Select3D_SensitiveCircle::GetConnected()
246 Standard_Boolean isFilled = mySensType == Select3D_TOS_INTERIOR;
247 // Create a copy of this
248 Handle(Select3D_SensitiveEntity) aNewEntity;
249 // this was constructed using Handle(Geom_Circle)
250 if (!Precision::IsInfinite (myCircle.Radius()))
252 if ((myEnd - myStart) > Precision::Confusion())
255 aNewEntity = new Select3D_SensitiveCircle (myOwnerId, myCircle, myStart, myEnd, isFilled);
260 aNewEntity = new Select3D_SensitiveCircle (myOwnerId, myCircle, isFilled);
263 // this was constructed using TColgp_Array1OfPnt
266 Standard_Integer aSize = myPolyg.Size();
267 TColgp_Array1OfPnt aPolyg (1, aSize);
268 for(Standard_Integer anIndex = 1; anIndex <= aSize; ++anIndex)
270 aPolyg.SetValue(anIndex, myPolyg.Pnt (anIndex-1));
272 aNewEntity = new Select3D_SensitiveCircle (myOwnerId, aPolyg, isFilled);
278 //=======================================================================
279 //function : computeCenter3D
281 //=======================================================================
282 void Select3D_SensitiveCircle::computeCenter3D()
285 Standard_Integer aNbPnts = myPolyg.Size();
288 // The mass of points system
289 Standard_Integer aMass = aNbPnts - 1;
290 // Find the circle barycenter
291 for (Standard_Integer anIndex = 0; anIndex < aNbPnts - 1; ++anIndex)
293 aCenter += myPolyg.Pnt(anIndex);
295 myCenter3D = aCenter / aMass;
299 myCenter3D = myPolyg.Pnt(0);
303 //=======================================================================
304 // function : CenterOfGeometry
305 // purpose : Returns center of the circle. If location transformation
306 // is set, it will be applied
307 //=======================================================================
308 gp_Pnt Select3D_SensitiveCircle::CenterOfGeometry() const
313 //=======================================================================
314 // function : distanceToCOG
316 //=======================================================================
317 Standard_Real Select3D_SensitiveCircle::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
319 return theMgr.DistToGeometryCenter (myCenter3D);