0022819: Redesign of OpenGl driver
[occt.git] / src / Select3D / Select3D_SensitiveCircle.cxx
CommitLineData
7fd59977 1// File: Select3D_SensitiveCircle.cxx
2// Created: Tue Feb 6 14:15:06 1996
3// Author: Robert COUBLANC
4// <rob@fidox>
5// Modified Tue Apr 14 1998 by rob : fix Bug : Case of Null Radius Circle...
6
7#include <Select3D_SensitiveCircle.ixx>
8#include <Precision.hxx>
9#include <gp_Lin2d.hxx>
10
11#include <CSLib_Class2d.hxx>
12#include <Select3D_SensitiveTriangle.hxx>
13#include <ElCLib.hxx>
14#include <Select3D_Pnt.hxx>
15#include <Select3D_Pnt2d.hxx>
329843e2 16#include <Select3D_Projector.hxx>
7fd59977 17
ac04d101 18
7fd59977 19static Standard_Integer S3D_GetCircleNBPoints(const Handle(Geom_Circle)& C,
20 const Standard_Integer anInputNumber)
21{
22 if(C->Radius()>Precision::Confusion())
23 return 2*anInputNumber+1;
24 return 1;
25}
ac04d101 26
7fd59977 27static Standard_Integer S3D_GetArcNBPoints(const Handle(Geom_Circle)& C,
28 const Standard_Integer anInputNumber)
29{
30 if(C->Radius()>Precision::Confusion())
31 return 2*anInputNumber-1;
32 return 1;
33}
ac04d101
SA
34
35//=======================================================================
36//function : Select3D_SensitiveCircle (constructor)
37//purpose : Definition of a sensitive circle
38//=======================================================================
39
7fd59977 40Select3D_SensitiveCircle::
41Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
ac04d101
SA
42 const Handle(Geom_Circle)& TheCircle,
43 const Standard_Boolean FilledCircle,
44 const Standard_Integer NbPoints):
7fd59977 45Select3D_SensitivePoly(OwnerId, S3D_GetCircleNBPoints(TheCircle,NbPoints)),
46myFillStatus(FilledCircle),
ac04d101
SA
47myDetectedIndex(-1),
48myCircle(TheCircle),
49mystart(0),
50myend(0)
7fd59977 51{
ac04d101
SA
52 if(mynbpoints!=1)
53 {
54 gp_Pnt p1,p2;
55 gp_Vec v1;
7fd59977 56 Standard_Real ustart = TheCircle->FirstParameter(),uend = TheCircle->LastParameter();
57 Standard_Real du = (uend-ustart)/NbPoints;
58 Standard_Real R = TheCircle->Radius();
59 Standard_Integer rank = 1;
60 Standard_Real curu =ustart;
61 for(Standard_Integer i=1;i<=NbPoints;i++)
62 {
63 TheCircle->D1(curu,p1,v1);
64
65 v1.Normalize();
66 ((Select3D_Pnt*)mypolyg3d)[rank-1] = p1;
67 rank++;
68 p2 = gp_Pnt(p1.X()+v1.X()*tan(du/2.)*R,
69 p1.Y()+v1.Y()*tan(du/2.)*R,
70 p1.Z()+v1.Z()*tan(du/2.)*R);
71 ((Select3D_Pnt*)mypolyg3d)[rank-1] = p2;
72 rank++;
73 curu+=du;
74 }
329843e2
A
75 ((Select3D_Pnt*)mypolyg3d)[NbPoints*2] = ((Select3D_Pnt*)mypolyg3d)[0];
76 // Get myCenter3D
77 myCenter3D = TheCircle->Location();
7fd59977 78 }
79 // Radius = 0.0
80 else
329843e2 81 {
7fd59977 82 ((Select3D_Pnt*)mypolyg3d)[0] = TheCircle->Location();
329843e2
A
83 // Get myCenter3D
84 myCenter3D = ((Select3D_Pnt*)mypolyg3d)[0];
85 }
7fd59977 86}
87
88//=======================================================================
ac04d101 89//function : Select3D_SensitiveCircle (constructor)
81bba717 90//purpose : Definition of a sensitive arc
7fd59977 91//=======================================================================
ac04d101 92
7fd59977 93Select3D_SensitiveCircle::
94Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
ac04d101
SA
95 const Handle(Geom_Circle)& TheCircle,
96 const Standard_Real u1,
97 const Standard_Real u2,
98 const Standard_Boolean FilledCircle,
99 const Standard_Integer NbPoints):
7fd59977 100Select3D_SensitivePoly(OwnerId, S3D_GetArcNBPoints(TheCircle,NbPoints)),
101myFillStatus(FilledCircle),
ac04d101
SA
102myDetectedIndex(-1),
103myCircle(TheCircle),
104mystart(u1),
105myend(u2)
7fd59977 106{
ac04d101
SA
107 if(mynbpoints > 1)
108 {
109 gp_Pnt p1,p2;
110 gp_Vec v1;
7fd59977 111
ac04d101
SA
112 if (u1 > u2)
113 {
114 mystart = u2;
115 myend = u1;
116 }
7fd59977 117
ac04d101 118 Standard_Real du = (myend-mystart)/(NbPoints-1);
7fd59977 119 Standard_Real R = TheCircle->Radius();
120 Standard_Integer rank = 1;
ac04d101 121 Standard_Real curu = mystart;
7fd59977 122
123 for(Standard_Integer i=1;i<=NbPoints-1;i++)
124 {
125 TheCircle->D1(curu,p1,v1);
126 v1.Normalize();
127 ((Select3D_Pnt*)mypolyg3d)[rank-1] = p1;
128 rank++;
129 p2 = gp_Pnt(p1.X()+v1.X()*tan(du/2.)*R,
130 p1.Y()+v1.Y()*tan(du/2.)*R,
131 p1.Z()+v1.Z()*tan(du/2.)*R);
132 ((Select3D_Pnt*)mypolyg3d)[rank-1] = p2;
133 rank++;
134 curu+=du;
135 }
ac04d101 136 TheCircle->D0(myend,p1);
329843e2
A
137 ((Select3D_Pnt*)mypolyg3d)[NbPoints*2-2] = p1;
138 // Get myCenter3D
139 myCenter3D = TheCircle->Location();
7fd59977 140 }
141 else
329843e2
A
142 {
143 ((Select3D_Pnt*)mypolyg3d)[0] = TheCircle->Location();
144 // Get myCenter3D
145 myCenter3D = ((Select3D_Pnt*)mypolyg3d)[0];
146 }
7fd59977 147}
148
149//=======================================================================
150//function : Select3D_SensitiveCircle
151//purpose :
152//=======================================================================
ac04d101 153
7fd59977 154Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
ac04d101
SA
155 const Handle(TColgp_HArray1OfPnt)& Thepolyg3d,
156 const Standard_Boolean FilledCircle):
7fd59977 157Select3D_SensitivePoly(OwnerId, Thepolyg3d),
158myFillStatus(FilledCircle),
ac04d101
SA
159myDetectedIndex(-1),
160mystart(0),
161myend(0)
7fd59977 162{
329843e2
A
163 if (mynbpoints > 1)
164 ComputeCenter3D();
165 else
166 myCenter3D = ((Select3D_Pnt*)mypolyg3d)[0];
7fd59977 167}
329843e2 168
ac04d101
SA
169//=======================================================================
170//function : Select3D_SensitiveCircle
171//purpose :
172//=======================================================================
173
7fd59977 174Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
ac04d101
SA
175 const TColgp_Array1OfPnt& Thepolyg3d,
176 const Standard_Boolean FilledCircle):
7fd59977 177Select3D_SensitivePoly(OwnerId, Thepolyg3d),
178myFillStatus(FilledCircle),
ac04d101
SA
179myDetectedIndex(-1),
180mystart(0),
181myend(0)
329843e2
A
182{
183 if (mynbpoints > 1)
184 ComputeCenter3D();
185 else
186 myCenter3D = ((Select3D_Pnt*)mypolyg3d)[0];
7fd59977 187}
188
ac04d101
SA
189//=======================================================================
190//function : Matches
191//purpose :
192//=======================================================================
193
7fd59977 194Standard_Boolean Select3D_SensitiveCircle::
195Matches(const Standard_Real X,
ac04d101
SA
196 const Standard_Real Y,
197 const Standard_Real aTol,
198 Standard_Real& DMin)
7fd59977 199{
329843e2
A
200 if(mynbpoints>1)
201 {
202 Standard_Boolean Found = Standard_False;
7fd59977 203 Standard_Integer i = 0;
7fd59977 204
329843e2
A
205 if(!myFillStatus)
206 {
207 while(i < mynbpoints-2 && !Found)
208 {
209 Standard_Integer TheStat =
210 Select3D_SensitiveTriangle::Status(((Select3D_Pnt2d*)mypolyg2d)[i],
7fd59977 211 ((Select3D_Pnt2d*)mypolyg2d)[i+1],
212 ((Select3D_Pnt2d*)mypolyg2d)[i+2],
329843e2
A
213 gp_XY(X,Y),aTol,DMin);
214 Found = (TheStat != 2);
215 if(Found) myDetectedIndex = i;
216 i += 2;
7fd59977 217 }
218 }
329843e2
A
219 else
220 {
7fd59977 221 myDetectedIndex =-1;
7fd59977 222 Standard_Real Xmin,Ymin,Xmax,Ymax;
329843e2
A
223
224 // Get coordinates of the bounding box
225 Bnd_Box2d(mybox2d).Get(Xmin,Ymin,Xmax,Ymax);
226 TColgp_Array1OfPnt2d anArrayOf2dPnt(1, mynbpoints);
227
228 // Fill anArrayOf2dPnt with points from mypolig2d
229 Points2D(anArrayOf2dPnt);
7fd59977 230
329843e2
A
231 CSLib_Class2d anInOutTool(anArrayOf2dPnt,aTol,aTol,Xmin,Ymin,Xmax,Ymax);
232
233 // Method SiDans returns the status :
234 // 1 - the point is inside the circle
235 // 0 - the point is on the circle
236 // -1 - the point is outside the circle
237 Standard_Integer aStat = anInOutTool.SiDans(gp_Pnt2d(X,Y));
238 if(aStat != -1)
239 {
240 // Compute DMin (a distance between the center and the point)
241 DMin = gp_XY(myCenter2D.x - X, myCenter2D.y - Y).Modulus();
242 Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
243 return Standard_True;
244 }
245 return Standard_False;
7fd59977 246 }
247 if(!Found)
248 myDetectedIndex=-1;
249 else
250 Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
251
252 return Found;
253 }
254 return Standard_True;
7fd59977 255}
329843e2 256
ac04d101
SA
257//=======================================================================
258//function : Matches
259//purpose :
260//=======================================================================
261
7fd59977 262Standard_Boolean Select3D_SensitiveCircle::
263Matches(const Standard_Real XMin,
ac04d101
SA
264 const Standard_Real YMin,
265 const Standard_Real XMax,
266 const Standard_Real YMax,
267 const Standard_Real aTol)
7fd59977 268{
269 myDetectedIndex =-1;
270 Bnd_Box2d abox;
271 abox.Update(Min(XMin,XMax),Min(YMin,YMax),Max(XMin,XMax),Max(YMin,YMax));
272 abox.Enlarge(aTol);
273 for(Standard_Integer i=0;i<mynbpoints;i++)
274 if(abox.IsOut(((Select3D_Pnt2d*)mypolyg2d)[i])) return Standard_False;
275
276 return Standard_True;
277}
278
7fd59977 279//=======================================================================
280//function : Matches
281//purpose :
282//=======================================================================
283
284Standard_Boolean Select3D_SensitiveCircle::
285Matches (const TColgp_Array1OfPnt2d& aPoly,
ac04d101
SA
286 const Bnd_Box2d& aBox,
287 const Standard_Real aTol)
7fd59977 288{
289 Standard_Real Umin,Vmin,Umax,Vmax;
290 aBox.Get(Umin,Vmin,Umax,Vmax);
291 Standard_Real Tolu,Tolv;
292 Tolu = 1e-7;
293 Tolv = 1e-7;
294 CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
295
ac04d101
SA
296 for(Standard_Integer j=1;j<=mynbpoints;j++)
297 {
7fd59977 298 Standard_Integer RES = aClassifier2d.SiDans(((Select3D_Pnt2d*)mypolyg2d)[j-1]);
299 if(RES!=1) return Standard_False;
300 }
301 return Standard_True;
302}
303
ac04d101
SA
304//=======================================================================
305//function : ArrayBounds
306//purpose :
307//=======================================================================
7fd59977 308
309void Select3D_SensitiveCircle::
310ArrayBounds(Standard_Integer & Low,
ac04d101 311 Standard_Integer & Up) const
7fd59977 312{
313 Low = 0;
314 Up = mynbpoints-1;
315}
316
ac04d101
SA
317//=======================================================================
318//function : GetPoint3d
319//purpose :
320//=======================================================================
7fd59977 321
322gp_Pnt Select3D_SensitiveCircle::
323GetPoint3d(const Standard_Integer Rank) const
324{
325 if(Rank>=0&& Rank<mynbpoints)
326 return ((Select3D_Pnt*)mypolyg3d)[Rank];
327 return ((Select3D_Pnt*)mypolyg3d)[0];
328}
329
330
331//=======================================================================
332//function : Dump
333//purpose :
334//=======================================================================
335
336void Select3D_SensitiveCircle::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
337{
338 // Standard_Integer rank(1);
339 gp_XYZ CDG(0.,0.,0.);
340
341 S<<"\tSensitiveCircle 3D :";
342
343 Standard_Boolean isclosed = 1== mynbpoints;
344 if(isclosed)
345 S<<"(Closed Circle)"<<endl;
346 else
347 S<<"(Arc Of Circle)"<<endl;
348
349 if(HasLocation())
350 S<<"\t\tExisting Location"<<endl;
351
352
ac04d101
SA
353 if(FullDump)
354 {
7fd59977 355 Standard_Integer EndIndex = isclosed? mynbpoints-2 : mynbpoints-1, nbpt(0);
ac04d101
SA
356 for(Standard_Integer i=0;i<EndIndex;i+=2)
357 {
7fd59977 358 CDG +=((Select3D_Pnt*)mypolyg3d)[i];
359 nbpt++;
360 }
361
362 CDG/=nbpt;
363
364 Standard_Real R = (CDG-((Select3D_Pnt*)mypolyg3d)[0]).Modulus();
365
366 S<<"\t\t Center : ("<<CDG.X()<<" , "<<CDG.Y()<<" , "<<CDG.Z()<<" )"<<endl;
367 S<<"\t\t Radius :"<<R<<endl;
368
369 }
370}
ac04d101
SA
371
372//=======================================================================
373//function : ComputeDepth
374//purpose :
375//=======================================================================
376
7fd59977 377Standard_Real Select3D_SensitiveCircle::ComputeDepth(const gp_Lin& EyeLine) const
378{
379 gp_Pnt CDG;
ac04d101
SA
380 if(myDetectedIndex==-1)
381 {
7fd59977 382 gp_XYZ CurCoord(((Select3D_Pnt*)mypolyg3d)[0]);
383 Standard_Boolean isclosed = 1==mynbpoints;
384 Standard_Integer EndIndex = isclosed ? mynbpoints-2 : mynbpoints-1, nbpt(0);
ac04d101
SA
385 for(Standard_Integer i=1;i<EndIndex;i+=2)
386 {
7fd59977 387 CurCoord +=((Select3D_Pnt*)mypolyg3d)[i];
388 nbpt++;
389 }
390 CDG.SetXYZ(CurCoord);
391 }
ac04d101
SA
392 else
393 {
7fd59977 394 gp_XYZ CurCoord(((Select3D_Pnt*)mypolyg3d)[myDetectedIndex]);
395 CurCoord+=((Select3D_Pnt*)mypolyg3d)[myDetectedIndex+1];
396 CurCoord+=((Select3D_Pnt*)mypolyg3d)[myDetectedIndex+2];
397 CDG.SetXYZ(CurCoord);
398 }
399
ac04d101 400 return ElCLib::Parameter(EyeLine,CDG);
7fd59977 401}
329843e2 402
ac04d101
SA
403//=======================================================================
404//function : GetConnected
405//purpose :
406//=======================================================================
407
408Handle(Select3D_SensitiveEntity) Select3D_SensitiveCircle::GetConnected(const TopLoc_Location& theLocation)
409{
410 // Create a copy of this
411 Handle(Select3D_SensitiveEntity) aNewEntity;
412 // this was constructed using Handle(Geom_Circle)
413 if(!myCircle.IsNull())
414 {
415 if((myend-mystart) > Precision::Confusion())
416 {
417 // Arc
418 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, myCircle, mystart, myend, myFillStatus);
419 }
420 else
421 {
422 // Circle
423 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, myCircle, myFillStatus);
424 }
425 }
426 // this was constructed using TColgp_Array1OfPnt
427 else
428 {
429 TColgp_Array1OfPnt aPolyg(1, mynbpoints);
430 for(Standard_Integer i = 1; i <= mynbpoints; ++i)
431 {
432 aPolyg.SetValue(i, ((Select3D_Pnt*)mypolyg3d)[i-1]);
433 }
434 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, aPolyg, myFillStatus);
435 }
436
437 if(HasLocation())
438 aNewEntity->SetLocation(Location());
439
440 aNewEntity->UpdateLocation(theLocation);
441
442 return aNewEntity;
443}
444
445//=======================================================================
446//function : Project
447//purpose :
448//=======================================================================
449
329843e2
A
450void Select3D_SensitiveCircle::Project(const Handle_Select3D_Projector &aProjector)
451{
452 Select3D_SensitivePoly::Project(aProjector);
453 // Project the center of the circle
454 gp_Pnt2d aCenter;
455 aProjector->Project(myCenter3D, aCenter);
456 myCenter2D = aCenter;
457}
458
ac04d101
SA
459//=======================================================================
460//function : ComputeCenter3D
461//purpose :
462//=======================================================================
463
329843e2
A
464void Select3D_SensitiveCircle::ComputeCenter3D()
465{
466 gp_XYZ aCenter(0., 0., 0.);
ac04d101 467 if(mynbpoints > 1)
329843e2
A
468 {
469 // The mass of points system
470 Standard_Integer aMass = mynbpoints - 1;
471 // Find the circle barycenter
ac04d101 472 for(Standard_Integer i = 0; i < mynbpoints-1; ++i)
329843e2
A
473 {
474 aCenter += ((Select3D_Pnt*)mypolyg3d)[i];
475 }
476 myCenter3D = aCenter / aMass;
477 }
ac04d101 478 else if (mynbpoints == 1)
329843e2
A
479 {
480 myCenter3D = ((Select3D_Pnt*)mypolyg3d)[0];
481 }
482 // bad case! there are no points in mypolyg3d
483 // It can lead to incorrect computation of
484 // parameter DMin in method Matches.
485 // In spite of this myCenter3D isn't left uninitialized
ac04d101
SA
486 else
487 {
329843e2
A
488 myCenter3D = aCenter;
489 }
490}