Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 1996-02-06 |
2 | // Created by: Robert COUBLANC | |
3 | // Copyright (c) 1996-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. | |
b311480e | 16 | |
f751596e | 17 | #include <Geom_Circle.hxx> |
7fd59977 | 18 | |
f751596e | 19 | #include <Select3D_Pnt.hxx> |
20 | #include <Select3D_SensitiveTriangle.hxx> | |
7fd59977 | 21 | #include <Precision.hxx> |
7fd59977 | 22 | |
f751596e | 23 | #include <Select3D_SensitiveCircle.hxx> |
7fd59977 | 24 | |
ac04d101 | 25 | |
f751596e | 26 | static Standard_Integer GetCircleNbPoints (const Handle(Geom_Circle)& theCircle, |
27 | const Standard_Integer theNbPnts) | |
ceae62f0 A |
28 | { |
29 | // Check if number of points is invalid. | |
f751596e | 30 | // In this case myPolyg raises Standard_ConstructionError |
ceae62f0 | 31 | // exception (look constructor bellow). |
f751596e | 32 | if (theNbPnts <= 0) |
ceae62f0 A |
33 | return 0; |
34 | ||
f751596e | 35 | if (theCircle->Radius() > Precision::Confusion()) |
36 | return 2 * theNbPnts + 1; | |
37 | ||
ceae62f0 | 38 | // The radius is too small and circle degenerates into point |
7fd59977 | 39 | return 1; |
40 | } | |
ac04d101 | 41 | |
f751596e | 42 | static Standard_Integer GetArcNbPoints (const Handle(Geom_Circle)& theCircle, |
43 | const Standard_Integer theNbPnts) | |
ceae62f0 A |
44 | { |
45 | // There is no need to check number of points here. | |
46 | // In case of invalid number of points this method returns | |
47 | // -1 or smaller value. | |
f751596e | 48 | if (theCircle->Radius() > Precision::Confusion()) |
49 | return 2 * theNbPnts - 1; | |
ceae62f0 A |
50 | |
51 | // The radius is too small and circle degenerates into point | |
7fd59977 | 52 | return 1; |
53 | } | |
ac04d101 SA |
54 | |
55 | //======================================================================= | |
56 | //function : Select3D_SensitiveCircle (constructor) | |
57 | //purpose : Definition of a sensitive circle | |
58 | //======================================================================= | |
f751596e | 59 | Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& theOwnerId, |
60 | const Handle(Geom_Circle)& theCircle, | |
61 | const Standard_Boolean theIsFilled, | |
62 | const Standard_Integer theNbPnts) | |
63 | : Select3D_SensitivePoly (theOwnerId, !theIsFilled, GetCircleNbPoints (theCircle, theNbPnts)), | |
64 | myCircle (theCircle), | |
65 | myStart (0), | |
66 | myEnd (0) | |
7fd59977 | 67 | { |
f751596e | 68 | mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY; |
69 | if (myPolyg.Size() != 1) | |
ac04d101 | 70 | { |
f751596e | 71 | gp_Pnt aP1, aP2; |
72 | gp_Vec aV1; | |
73 | Standard_Real anUStart = theCircle->FirstParameter(); | |
74 | Standard_Real anUEnd = theCircle->LastParameter(); | |
75 | Standard_Real aStep = (anUEnd - anUStart) / theNbPnts; | |
76 | Standard_Real aRadius = theCircle->Radius(); | |
77 | Standard_Integer aPntIdx = 1; | |
78 | Standard_Real aCurU = anUStart; | |
79 | for (Standard_Integer anIndex = 1; anIndex <= theNbPnts; anIndex++) | |
7fd59977 | 80 | { |
f751596e | 81 | theCircle->D1 (aCurU, aP1, aV1); |
82 | ||
83 | aV1.Normalize(); | |
84 | myPolyg.SetPnt (aPntIdx - 1, aP1); | |
85 | aPntIdx++; | |
86 | aP2 = gp_Pnt (aP1.X() + aV1.X() * tan (aStep / 2.0) * aRadius, | |
87 | aP1.Y() + aV1.Y() * tan (aStep / 2.0) * aRadius, | |
88 | aP1.Z() + aV1.Z() * tan (aStep / 2.0) * aRadius); | |
89 | myPolyg.SetPnt (aPntIdx - 1, aP2); | |
90 | aPntIdx++; | |
91 | aCurU += aStep; | |
7fd59977 | 92 | } |
ceae62f0 | 93 | |
f751596e | 94 | // Copy the first point to the last point of myPolyg |
95 | myPolyg.SetPnt (theNbPnts * 2, myPolyg.Pnt (0)); | |
ceae62f0 | 96 | // Get myCenter3D |
f751596e | 97 | myCenter3D = theCircle->Location(); |
7fd59977 | 98 | } |
99 | // Radius = 0.0 | |
100 | else | |
329843e2 | 101 | { |
f751596e | 102 | myPolyg.SetPnt (0, theCircle->Location()); |
329843e2 | 103 | // Get myCenter3D |
f751596e | 104 | myCenter3D = myPolyg.Pnt (0); |
105 | } | |
106 | ||
107 | if (mySensType == Select3D_TOS_BOUNDARY) | |
108 | { | |
109 | SetSensitivityFactor (6.0); | |
329843e2 | 110 | } |
7fd59977 | 111 | } |
112 | ||
113 | //======================================================================= | |
ac04d101 | 114 | //function : Select3D_SensitiveCircle (constructor) |
81bba717 | 115 | //purpose : Definition of a sensitive arc |
7fd59977 | 116 | //======================================================================= |
f751596e | 117 | Select3D_SensitiveCircle::Select3D_SensitiveCircle (const Handle(SelectBasics_EntityOwner)& theOwnerId, |
118 | const Handle(Geom_Circle)& theCircle, | |
119 | const Standard_Real theU1, | |
120 | const Standard_Real theU2, | |
121 | const Standard_Boolean theIsFilled, | |
122 | const Standard_Integer theNbPnts) | |
123 | : Select3D_SensitivePoly (theOwnerId, !theIsFilled, GetArcNbPoints (theCircle, theNbPnts)), | |
124 | myCircle (theCircle), | |
125 | myStart (Min (theU1, theU2)), | |
126 | myEnd (Max (theU1, theU2)) | |
7fd59977 | 127 | { |
f751596e | 128 | mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY; |
aec37c15 | 129 | |
f751596e | 130 | if (myPolyg.Size() != 1) |
131 | { | |
132 | gp_Pnt aP1, aP2; | |
133 | gp_Vec aV1; | |
aec37c15 | 134 | |
f751596e | 135 | Standard_Real aStep = (myEnd - myStart) / (theNbPnts - 1); |
136 | Standard_Real aRadius = theCircle->Radius(); | |
137 | Standard_Integer aPntIdx = 1; | |
138 | Standard_Real aCurU = myStart; | |
aec37c15 | 139 | |
f751596e | 140 | for (Standard_Integer anIndex = 1; anIndex <= theNbPnts - 1; anIndex++) |
7fd59977 | 141 | { |
f751596e | 142 | theCircle->D1 (aCurU, aP1, aV1); |
143 | aV1.Normalize(); | |
144 | myPolyg.SetPnt (aPntIdx - 1, aP1); | |
145 | aPntIdx++; | |
146 | aP2 = gp_Pnt (aP1.X() + aV1.X() * tan (aStep /2.0) * aRadius, | |
147 | aP1.Y() + aV1.Y() * tan (aStep /2.0) * aRadius, | |
148 | aP1.Z() + aV1.Z() * tan (aStep /2.0) * aRadius); | |
149 | myPolyg.SetPnt (aPntIdx - 1, aP2); | |
150 | aPntIdx++; | |
151 | aCurU += aStep; | |
7fd59977 | 152 | } |
f751596e | 153 | theCircle->D0 (myEnd, aP1); |
154 | myPolyg.SetPnt (theNbPnts * 2 - 2, aP1); | |
aec37c15 | 155 | // Get myCenter3D |
f751596e | 156 | myCenter3D = theCircle->Location(); |
7fd59977 | 157 | } |
158 | else | |
329843e2 | 159 | { |
f751596e | 160 | myPolyg.SetPnt (0, theCircle->Location()); |
329843e2 | 161 | // Get myCenter3D |
f751596e | 162 | myCenter3D = myPolyg.Pnt (0); |
329843e2 | 163 | } |
7fd59977 | 164 | |
f751596e | 165 | if (mySensType == Select3D_TOS_BOUNDARY) |
166 | { | |
167 | SetSensitivityFactor (6.0); | |
168 | } | |
7fd59977 | 169 | } |
329843e2 | 170 | |
ac04d101 SA |
171 | //======================================================================= |
172 | //function : Select3D_SensitiveCircle | |
aec37c15 | 173 | //purpose : |
ac04d101 | 174 | //======================================================================= |
f751596e | 175 | Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& theOwnerId, |
176 | const Handle(TColgp_HArray1OfPnt)& thePnts3d, | |
177 | const Standard_Boolean theIsFilled) | |
ee2038c0 | 178 | : Select3D_SensitivePoly (theOwnerId, thePnts3d, (Standard_Boolean )!theIsFilled), |
f751596e | 179 | myStart (0), |
180 | myEnd (0) | |
ceae62f0 | 181 | { |
f751596e | 182 | mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY; |
183 | ||
184 | if (myPolyg.Size() != 1) | |
185 | computeCenter3D(); | |
ceae62f0 | 186 | else |
f751596e | 187 | myCenter3D = myPolyg.Pnt (0); |
188 | ||
189 | if (mySensType == Select3D_TOS_BOUNDARY) | |
190 | { | |
191 | SetSensitivityFactor (6.0); | |
192 | } | |
7fd59977 | 193 | } |
194 | ||
ac04d101 | 195 | //======================================================================= |
f751596e | 196 | //function : Select3D_SensitiveCircle |
aec37c15 | 197 | //purpose : |
ac04d101 SA |
198 | //======================================================================= |
199 | ||
f751596e | 200 | Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& theOwnerId, |
201 | const TColgp_Array1OfPnt& thePnts3d, | |
202 | const Standard_Boolean theIsFilled) | |
203 | : Select3D_SensitivePoly (theOwnerId, thePnts3d, !theIsFilled), | |
204 | myStart (0), | |
205 | myEnd (0) | |
7fd59977 | 206 | { |
f751596e | 207 | mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY; |
4269bd1b | 208 | |
f751596e | 209 | if (myPolyg.Size() != 1) |
210 | computeCenter3D(); | |
211 | else | |
212 | myCenter3D = myPolyg.Pnt (0); | |
4269bd1b | 213 | |
f751596e | 214 | if (mySensType == Select3D_TOS_BOUNDARY) |
4269bd1b | 215 | { |
f751596e | 216 | SetSensitivityFactor (6.0); |
4269bd1b | 217 | } |
7fd59977 | 218 | } |
329843e2 | 219 | |
ac04d101 | 220 | //======================================================================= |
f751596e | 221 | // function : BVH |
222 | // purpose : Builds BVH tree for a circle's edge segments if needed | |
ac04d101 | 223 | //======================================================================= |
f751596e | 224 | void Select3D_SensitiveCircle::BVH() |
7fd59977 | 225 | { |
f751596e | 226 | if (mySensType == Select3D_TOS_BOUNDARY) |
ceae62f0 | 227 | { |
f751596e | 228 | Select3D_SensitivePoly::BVH(); |
ceae62f0 | 229 | } |
7fd59977 | 230 | } |
231 | ||
7fd59977 | 232 | //======================================================================= |
f751596e | 233 | // function : Matches |
234 | // purpose : Checks whether the circle overlaps current selecting volume | |
7fd59977 | 235 | //======================================================================= |
f751596e | 236 | Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolumeManager& theMgr, |
237 | SelectBasics_PickResult& thePickResult) | |
ceae62f0 | 238 | { |
f751596e | 239 | Standard_Real aDepth = RealLast(); |
240 | Standard_Real aDistToCOG = RealLast(); | |
7fd59977 | 241 | |
f751596e | 242 | if (mySensType == Select3D_TOS_BOUNDARY) |
ac04d101 | 243 | { |
2157d6ac | 244 | if (!Select3D_SensitivePoly::Matches (theMgr, thePickResult)) |
245 | { | |
246 | thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG); | |
247 | return Standard_False; | |
248 | } | |
f751596e | 249 | } |
250 | else if (mySensType == Select3D_TOS_INTERIOR) | |
251 | { | |
252 | Handle(TColgp_HArray1OfPnt) anArrayOfPnt; | |
253 | Points3D (anArrayOfPnt); | |
2157d6ac | 254 | if (!theMgr.IsOverlapAllowed()) |
255 | { | |
256 | thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG); | |
14cda02f | 257 | for (Standard_Integer aPntIdx = anArrayOfPnt->Lower(); aPntIdx <= anArrayOfPnt->Upper(); ++aPntIdx) |
2157d6ac | 258 | { |
14cda02f | 259 | Standard_Real aDummy; |
260 | if (!theMgr.Overlaps (anArrayOfPnt->Value (aPntIdx), aDummy)) | |
261 | return Standard_False; | |
2157d6ac | 262 | } |
263 | return Standard_True; | |
264 | } | |
7fd59977 | 265 | |
2157d6ac | 266 | if (!theMgr.Overlaps (anArrayOfPnt, Select3D_TOS_INTERIOR, aDepth)) |
267 | { | |
268 | thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG); | |
269 | return Standard_False; | |
270 | } | |
f751596e | 271 | } |
7fd59977 | 272 | |
273 | ||
2157d6ac | 274 | aDistToCOG = theMgr.DistToGeometryCenter (myCenter3D); |
275 | thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG); | |
276 | return Standard_True; | |
7fd59977 | 277 | } |
278 | ||
f751596e | 279 | void Select3D_SensitiveCircle::ArrayBounds (Standard_Integer & theLow, |
280 | Standard_Integer & theUp) const | |
7fd59977 | 281 | { |
f751596e | 282 | theLow = 0; |
283 | theUp = myPolyg.Size() - 1; | |
7fd59977 | 284 | } |
ac04d101 SA |
285 | |
286 | //======================================================================= | |
f751596e | 287 | //function : GetPoint3d |
aec37c15 | 288 | //purpose : |
ac04d101 | 289 | //======================================================================= |
f751596e | 290 | gp_Pnt Select3D_SensitiveCircle::GetPoint3d (const Standard_Integer thePntIdx) const |
7fd59977 | 291 | { |
f751596e | 292 | if (thePntIdx >= 0 && thePntIdx < myPolyg.Size()) |
293 | return myPolyg.Pnt (thePntIdx); | |
4269bd1b | 294 | |
f751596e | 295 | return gp_Pnt(); |
7fd59977 | 296 | } |
329843e2 | 297 | |
ac04d101 SA |
298 | //======================================================================= |
299 | //function : GetConnected | |
aec37c15 | 300 | //purpose : |
ceae62f0 | 301 | //======================================================================= |
ac04d101 | 302 | |
f751596e | 303 | Handle(Select3D_SensitiveEntity) Select3D_SensitiveCircle::GetConnected() |
ac04d101 | 304 | { |
f751596e | 305 | Standard_Boolean isFilled = mySensType == Select3D_TOS_INTERIOR; |
aec37c15 | 306 | // Create a copy of this |
ac04d101 SA |
307 | Handle(Select3D_SensitiveEntity) aNewEntity; |
308 | // this was constructed using Handle(Geom_Circle) | |
309 | if(!myCircle.IsNull()) | |
310 | { | |
f751596e | 311 | if ((myEnd - myStart) > Precision::Confusion()) |
ac04d101 SA |
312 | { |
313 | // Arc | |
f751596e | 314 | aNewEntity = new Select3D_SensitiveCircle (myOwnerId, myCircle, myStart, myEnd, isFilled); |
ac04d101 SA |
315 | } |
316 | else | |
317 | { | |
318 | // Circle | |
f751596e | 319 | aNewEntity = new Select3D_SensitiveCircle (myOwnerId, myCircle, isFilled); |
ac04d101 SA |
320 | } |
321 | } | |
322 | // this was constructed using TColgp_Array1OfPnt | |
aec37c15 | 323 | else |
ac04d101 | 324 | { |
f751596e | 325 | Standard_Integer aSize = myPolyg.Size(); |
326 | TColgp_Array1OfPnt aPolyg (1, aSize); | |
ceae62f0 | 327 | for(Standard_Integer anIndex = 1; anIndex <= aSize; ++anIndex) |
ac04d101 | 328 | { |
f751596e | 329 | aPolyg.SetValue(anIndex, myPolyg.Pnt (anIndex-1)); |
ac04d101 | 330 | } |
f751596e | 331 | aNewEntity = new Select3D_SensitiveCircle (myOwnerId, aPolyg, isFilled); |
ac04d101 SA |
332 | } |
333 | ||
ac04d101 SA |
334 | return aNewEntity; |
335 | } | |
336 | ||
337 | //======================================================================= | |
f751596e | 338 | //function : computeCenter3D |
aec37c15 | 339 | //purpose : |
ac04d101 | 340 | //======================================================================= |
f751596e | 341 | void Select3D_SensitiveCircle::computeCenter3D() |
329843e2 | 342 | { |
ceae62f0 | 343 | gp_XYZ aCenter; |
f751596e | 344 | Standard_Integer aNbPnts = myPolyg.Size(); |
345 | if (aNbPnts != 1) | |
329843e2 A |
346 | { |
347 | // The mass of points system | |
f751596e | 348 | Standard_Integer aMass = aNbPnts - 1; |
329843e2 | 349 | // Find the circle barycenter |
f751596e | 350 | for (Standard_Integer anIndex = 0; anIndex < aNbPnts - 1; ++anIndex) |
329843e2 | 351 | { |
f751596e | 352 | aCenter += myPolyg.Pnt(anIndex); |
329843e2 A |
353 | } |
354 | myCenter3D = aCenter / aMass; | |
355 | } | |
ac04d101 SA |
356 | else |
357 | { | |
f751596e | 358 | myCenter3D = myPolyg.Pnt(0); |
329843e2 A |
359 | } |
360 | } | |
f751596e | 361 | |
362 | //======================================================================= | |
363 | // function : CenterOfGeometry | |
364 | // purpose : Returns center of the circle. If location transformation | |
365 | // is set, it will be applied | |
366 | //======================================================================= | |
367 | gp_Pnt Select3D_SensitiveCircle::CenterOfGeometry() const | |
368 | { | |
369 | return myCenter3D; | |
370 | } |