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