0024070: OpenGL capped object-level clipping planes
[occt.git] / src / Select3D / Select3D_SensitiveCircle.cxx
CommitLineData
b311480e 1// Created on: 1996-02-06
2// Created by: Robert COUBLANC
3// Copyright (c) 1996-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21// Modified Tue Apr 14 1998 by rob : fix Bug : Case of Null Radius Circle...
22
23#include <Select3D_SensitiveCircle.ixx>
24#include <Precision.hxx>
25#include <gp_Lin2d.hxx>
26
27#include <CSLib_Class2d.hxx>
28#include <Select3D_SensitiveTriangle.hxx>
29#include <ElCLib.hxx>
30#include <Select3D_Pnt.hxx>
31#include <Select3D_Pnt2d.hxx>
329843e2 32#include <Select3D_Projector.hxx>
7fd59977 33
ac04d101 34
7fd59977 35static Standard_Integer S3D_GetCircleNBPoints(const Handle(Geom_Circle)& C,
36 const Standard_Integer anInputNumber)
ceae62f0
A
37{
38 // Check if number of points is invalid.
39 // In this case mypolyg raises Standard_ConstructionError
40 // exception (look constructor bellow).
41 if (anInputNumber <= 0)
42 return 0;
43
44 if (C->Radius()>Precision::Confusion())
7fd59977 45 return 2*anInputNumber+1;
ceae62f0 46 // The radius is too small and circle degenerates into point
7fd59977 47 return 1;
48}
ac04d101 49
7fd59977 50static Standard_Integer S3D_GetArcNBPoints(const Handle(Geom_Circle)& C,
51 const Standard_Integer anInputNumber)
ceae62f0
A
52{
53 // There is no need to check number of points here.
54 // In case of invalid number of points this method returns
55 // -1 or smaller value.
56 if (C->Radius()>Precision::Confusion())
7fd59977 57 return 2*anInputNumber-1;
ceae62f0
A
58
59 // The radius is too small and circle degenerates into point
7fd59977 60 return 1;
61}
ac04d101
SA
62
63//=======================================================================
64//function : Select3D_SensitiveCircle (constructor)
65//purpose : Definition of a sensitive circle
66//=======================================================================
67
7fd59977 68Select3D_SensitiveCircle::
aec37c15 69Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
70 const Handle(Geom_Circle)& TheCircle,
ac04d101
SA
71 const Standard_Boolean FilledCircle,
72 const Standard_Integer NbPoints):
7fd59977 73Select3D_SensitivePoly(OwnerId, S3D_GetCircleNBPoints(TheCircle,NbPoints)),
74myFillStatus(FilledCircle),
ceae62f0
A
75myCircle(TheCircle),
76mystart(0),
ac04d101 77myend(0)
7fd59977 78{
ceae62f0 79 if (mypolyg.Size() != 1)
ac04d101
SA
80 {
81 gp_Pnt p1,p2;
82 gp_Vec v1;
7fd59977 83 Standard_Real ustart = TheCircle->FirstParameter(),uend = TheCircle->LastParameter();
84 Standard_Real du = (uend-ustart)/NbPoints;
85 Standard_Real R = TheCircle->Radius();
86 Standard_Integer rank = 1;
87 Standard_Real curu =ustart;
ceae62f0 88 for(Standard_Integer anIndex=1;anIndex<=NbPoints;anIndex++)
7fd59977 89 {
90 TheCircle->D1(curu,p1,v1);
aec37c15 91
7fd59977 92 v1.Normalize();
ceae62f0 93 mypolyg.SetPnt(rank-1, p1);
7fd59977 94 rank++;
95 p2 = gp_Pnt(p1.X()+v1.X()*tan(du/2.)*R,
96 p1.Y()+v1.Y()*tan(du/2.)*R,
97 p1.Z()+v1.Z()*tan(du/2.)*R);
ceae62f0 98 mypolyg.SetPnt(rank-1, p2);
7fd59977 99 rank++;
100 curu+=du;
101 }
ceae62f0
A
102
103 // Copy the first point to the last point of mypolyg
104 mypolyg.SetPnt(NbPoints*2, mypolyg.Pnt(0));
105 // Get myCenter3D
329843e2 106 myCenter3D = TheCircle->Location();
7fd59977 107 }
108 // Radius = 0.0
109 else
329843e2 110 {
ceae62f0 111 mypolyg.SetPnt(0, TheCircle->Location());
329843e2 112 // Get myCenter3D
ceae62f0 113 myCenter3D = mypolyg.Pnt(0);
329843e2 114 }
7fd59977 115}
116
117//=======================================================================
ac04d101 118//function : Select3D_SensitiveCircle (constructor)
81bba717 119//purpose : Definition of a sensitive arc
7fd59977 120//=======================================================================
ac04d101 121
7fd59977 122Select3D_SensitiveCircle::
aec37c15 123Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
ac04d101
SA
124 const Handle(Geom_Circle)& TheCircle,
125 const Standard_Real u1,
126 const Standard_Real u2,
127 const Standard_Boolean FilledCircle,
128 const Standard_Integer NbPoints):
7fd59977 129Select3D_SensitivePoly(OwnerId, S3D_GetArcNBPoints(TheCircle,NbPoints)),
130myFillStatus(FilledCircle),
ceae62f0
A
131myCircle(TheCircle),
132mystart(u1),
ac04d101 133myend(u2)
7fd59977 134{
ceae62f0 135 if (mypolyg.Size() != 1)
ac04d101
SA
136 {
137 gp_Pnt p1,p2;
138 gp_Vec v1;
aec37c15 139
ceae62f0 140 if (u1 > u2)
ac04d101 141 {
ceae62f0 142 mystart = u2;
ac04d101
SA
143 myend = u1;
144 }
aec37c15 145
ac04d101 146 Standard_Real du = (myend-mystart)/(NbPoints-1);
7fd59977 147 Standard_Real R = TheCircle->Radius();
148 Standard_Integer rank = 1;
ceae62f0 149 Standard_Real curu = mystart;
aec37c15 150
ceae62f0 151 for(Standard_Integer anIndex=1;anIndex<=NbPoints-1;anIndex++)
7fd59977 152 {
153 TheCircle->D1(curu,p1,v1);
154 v1.Normalize();
ceae62f0 155 mypolyg.SetPnt(rank-1, p1);
7fd59977 156 rank++;
157 p2 = gp_Pnt(p1.X()+v1.X()*tan(du/2.)*R,
158 p1.Y()+v1.Y()*tan(du/2.)*R,
159 p1.Z()+v1.Z()*tan(du/2.)*R);
ceae62f0 160 mypolyg.SetPnt(rank-1, p2);
7fd59977 161 rank++;
162 curu+=du;
163 }
ac04d101 164 TheCircle->D0(myend,p1);
ceae62f0 165 mypolyg.SetPnt(NbPoints*2-2, p1);
aec37c15 166 // Get myCenter3D
329843e2 167 myCenter3D = TheCircle->Location();
7fd59977 168 }
169 else
329843e2 170 {
ceae62f0 171 mypolyg.SetPnt(0, TheCircle->Location());
329843e2 172 // Get myCenter3D
ceae62f0 173 myCenter3D = mypolyg.Pnt(0);
329843e2 174 }
7fd59977 175}
176
177//=======================================================================
178//function : Select3D_SensitiveCircle
aec37c15 179//purpose :
7fd59977 180//=======================================================================
ac04d101 181
7fd59977 182Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
ac04d101
SA
183 const Handle(TColgp_HArray1OfPnt)& Thepolyg3d,
184 const Standard_Boolean FilledCircle):
7fd59977 185Select3D_SensitivePoly(OwnerId, Thepolyg3d),
186myFillStatus(FilledCircle),
ceae62f0 187mystart(0),
ac04d101 188myend(0)
7fd59977 189{
ceae62f0 190 if (mypolyg.Size() != 1)
329843e2 191 ComputeCenter3D();
ceae62f0
A
192 else
193 myCenter3D = mypolyg.Pnt(0);
7fd59977 194}
329843e2 195
ac04d101
SA
196//=======================================================================
197//function : Select3D_SensitiveCircle
aec37c15 198//purpose :
ac04d101
SA
199//=======================================================================
200
7fd59977 201Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
ac04d101
SA
202 const TColgp_Array1OfPnt& Thepolyg3d,
203 const Standard_Boolean FilledCircle):
7fd59977 204Select3D_SensitivePoly(OwnerId, Thepolyg3d),
205myFillStatus(FilledCircle),
ceae62f0 206mystart(0),
ac04d101 207myend(0)
ceae62f0
A
208{
209 if (mypolyg.Size() != 1)
329843e2 210 ComputeCenter3D();
ceae62f0
A
211 else
212 myCenter3D = mypolyg.Pnt(0);
7fd59977 213}
214
ac04d101
SA
215//=======================================================================
216//function : Matches
aec37c15 217//purpose :
ac04d101
SA
218//=======================================================================
219
4269bd1b 220Standard_Boolean Select3D_SensitiveCircle::Matches (const SelectBasics_PickArgs& thePickArgs,
221 Standard_Real& theMatchDMin,
222 Standard_Real& theMatchDepth)
7fd59977 223{
ceae62f0 224 Standard_Integer aSize = mypolyg.Size();
4269bd1b 225 Standard_Integer aDetectedIndex = -1;
226 gp_XY aPickXY (thePickArgs.X(), thePickArgs.Y());
ceae62f0 227 if (aSize != 1)
329843e2
A
228 {
229 Standard_Boolean Found = Standard_False;
ceae62f0 230 Standard_Integer anIndex = 0;
aec37c15 231
329843e2
A
232 if(!myFillStatus)
233 {
ceae62f0
A
234 while(anIndex < aSize-2 && !Found)
235 {
236 Standard_Integer TheStat =
237 Select3D_SensitiveTriangle::Status(mypolyg.Pnt2d(anIndex),
238 mypolyg.Pnt2d(anIndex+1),
239 mypolyg.Pnt2d(anIndex+2),
4269bd1b 240 aPickXY, thePickArgs.Tolerance(),
241 theMatchDMin);
ceae62f0 242 Found = (TheStat != 2);
4269bd1b 243 if (Found)
244 {
245 aDetectedIndex = anIndex;
246 }
247
ceae62f0 248 anIndex += 2;
7fd59977 249 }
250 }
ceae62f0 251 else
329843e2 252 {
7fd59977 253 Standard_Real Xmin,Ymin,Xmax,Ymax;
329843e2
A
254
255 // Get coordinates of the bounding box
ceae62f0
A
256 Bnd_Box2d(mybox2d).Get(Xmin,Ymin,Xmax,Ymax);
257 TColgp_Array1OfPnt2d anArrayOf2dPnt(1, aSize);
258
329843e2 259 // Fill anArrayOf2dPnt with points from mypolig2d
ceae62f0 260 Points2D(anArrayOf2dPnt);
aec37c15 261
4269bd1b 262 CSLib_Class2d anInOutTool (anArrayOf2dPnt,
263 thePickArgs.Tolerance(),
264 thePickArgs.Tolerance(),
265 Xmin, Ymin, Xmax, Ymax);
329843e2
A
266
267 // Method SiDans returns the status :
aec37c15 268 // 1 - the point is inside the circle
329843e2
A
269 // 0 - the point is on the circle
270 // -1 - the point is outside the circle
4269bd1b 271 Standard_Integer aStat = anInOutTool.SiDans (gp_Pnt2d (aPickXY));
ceae62f0 272 if(aStat != -1)
329843e2
A
273 {
274 // Compute DMin (a distance between the center and the point)
4269bd1b 275 theMatchDMin = gp_XY (myCenter2D.x - aPickXY.X(), myCenter2D.y - aPickXY.Y()).Modulus();
276
277 theMatchDepth = ComputeDepth (thePickArgs.PickLine(), aDetectedIndex);
278
279 return !thePickArgs.IsClipped (theMatchDepth);
329843e2 280 }
4269bd1b 281
ceae62f0 282 return Standard_False;
7fd59977 283 }
4269bd1b 284
285 if (Found)
286 {
287 theMatchDepth = ComputeDepth (thePickArgs.PickLine(), aDetectedIndex);
288
289 return !thePickArgs.IsClipped (theMatchDepth);
290 }
291
292 return Standard_False;
7fd59977 293 }
4269bd1b 294
ceae62f0 295 // Circle degenerates into point
4269bd1b 296 theMatchDMin = gp_Pnt2d(aPickXY).Distance(mypolyg.Pnt2d(0));
297 if (theMatchDMin <= thePickArgs.Tolerance() * SensitivityFactor())
298 {
299 theMatchDepth = ComputeDepth (thePickArgs.PickLine(), aDetectedIndex);
300
301 return !thePickArgs.IsClipped (theMatchDepth);
302 }
ceae62f0
A
303
304 return Standard_False;
7fd59977 305}
329843e2 306
ac04d101
SA
307//=======================================================================
308//function : Matches
aec37c15 309//purpose :
ac04d101
SA
310//=======================================================================
311
7fd59977 312Standard_Boolean Select3D_SensitiveCircle::
313Matches(const Standard_Real XMin,
ac04d101
SA
314 const Standard_Real YMin,
315 const Standard_Real XMax,
316 const Standard_Real YMax,
317 const Standard_Real aTol)
7fd59977 318{
7fd59977 319 Bnd_Box2d abox;
320 abox.Update(Min(XMin,XMax),Min(YMin,YMax),Max(XMin,XMax),Max(YMin,YMax));
321 abox.Enlarge(aTol);
7fd59977 322
ceae62f0
A
323 for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();anIndex++)
324 {
325 if(abox.IsOut(mypolyg.Pnt2d(anIndex)))
326 return Standard_False;
327 }
7fd59977 328 return Standard_True;
329}
330
7fd59977 331//=======================================================================
332//function : Matches
aec37c15 333//purpose :
7fd59977 334//=======================================================================
335
336Standard_Boolean Select3D_SensitiveCircle::
337Matches (const TColgp_Array1OfPnt2d& aPoly,
ac04d101
SA
338 const Bnd_Box2d& aBox,
339 const Standard_Real aTol)
ceae62f0 340{
7fd59977 341 Standard_Real Umin,Vmin,Umax,Vmax;
342 aBox.Get(Umin,Vmin,Umax,Vmax);
7fd59977 343 CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
344
ceae62f0 345 for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();++anIndex)
ac04d101 346 {
ceae62f0
A
347 Standard_Integer RES = aClassifier2d.SiDans(mypolyg.Pnt2d(anIndex));
348 if(RES!=1)
349 return Standard_False;
7fd59977 350 }
351 return Standard_True;
352}
353
ac04d101
SA
354//=======================================================================
355//function : ArrayBounds
aec37c15 356//purpose :
ac04d101 357//=======================================================================
7fd59977 358
359void Select3D_SensitiveCircle::
360ArrayBounds(Standard_Integer & Low,
ac04d101 361 Standard_Integer & Up) const
7fd59977 362{
ceae62f0
A
363 Low = 0;
364 Up = mypolyg.Size()-1;
7fd59977 365}
366
ac04d101
SA
367//=======================================================================
368//function : GetPoint3d
aec37c15 369//purpose :
ac04d101 370//=======================================================================
7fd59977 371
372gp_Pnt Select3D_SensitiveCircle::
373GetPoint3d(const Standard_Integer Rank) const
374{
ceae62f0
A
375 if(Rank>=0 && Rank<mypolyg.Size())
376 return mypolyg.Pnt(Rank);
377 return gp_Pnt();
7fd59977 378}
379
380
381//=======================================================================
382//function : Dump
aec37c15 383//purpose :
7fd59977 384//=======================================================================
385
386void Select3D_SensitiveCircle::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
387{
ceae62f0 388 Standard_Integer aSize = mypolyg.Size();
aec37c15 389
7fd59977 390 S<<"\tSensitiveCircle 3D :";
aec37c15 391
ceae62f0 392 Standard_Boolean isclosed = 1== aSize;
7fd59977 393 if(isclosed)
394 S<<"(Closed Circle)"<<endl;
395 else
396 S<<"(Arc Of Circle)"<<endl;
aec37c15 397
7fd59977 398 if(HasLocation())
399 S<<"\t\tExisting Location"<<endl;
aec37c15 400
7fd59977 401
ac04d101
SA
402 if(FullDump)
403 {
ceae62f0
A
404 gp_XYZ aCenter = myCenter3D;
405 Standard_Real R = (aCenter-mypolyg.Pnt(0)).Modulus();
406
407 S<<"\t\t Center : ("<<aCenter.X()<<" , "<<aCenter.Y()<<" , "<<aCenter.Z()<<" )"<<endl;
7fd59977 408 S<<"\t\t Radius :"<<R<<endl;
7fd59977 409 }
410}
ac04d101
SA
411
412//=======================================================================
413//function : ComputeDepth
aec37c15 414//purpose :
ac04d101
SA
415//=======================================================================
416
4269bd1b 417Standard_Real Select3D_SensitiveCircle::ComputeDepth (const gp_Lin& thePickLine,
418 const Standard_Integer theDetectedIndex) const
7fd59977 419{
ceae62f0 420 gp_XYZ aCDG;
4269bd1b 421 if (theDetectedIndex == -1)
ac04d101 422 {
ceae62f0 423 aCDG = myCenter3D;
7fd59977 424 }
ac04d101
SA
425 else
426 {
4269bd1b 427 aCDG += mypolyg.Pnt (theDetectedIndex);
428 aCDG += mypolyg.Pnt (theDetectedIndex + 1);
429 aCDG += mypolyg.Pnt (theDetectedIndex + 2);
ceae62f0 430 aCDG /= 3.;
7fd59977 431 }
4269bd1b 432
433 return ElCLib::Parameter (thePickLine, gp_Pnt (aCDG));
7fd59977 434}
329843e2 435
ac04d101
SA
436//=======================================================================
437//function : GetConnected
aec37c15 438//purpose :
ceae62f0 439//=======================================================================
ac04d101 440
aec37c15 441Handle(Select3D_SensitiveEntity) Select3D_SensitiveCircle::GetConnected(const TopLoc_Location& theLocation)
ac04d101 442{
aec37c15 443 // Create a copy of this
ac04d101
SA
444 Handle(Select3D_SensitiveEntity) aNewEntity;
445 // this was constructed using Handle(Geom_Circle)
446 if(!myCircle.IsNull())
447 {
448 if((myend-mystart) > Precision::Confusion())
449 {
450 // Arc
451 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, myCircle, mystart, myend, myFillStatus);
452 }
453 else
454 {
455 // Circle
456 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, myCircle, myFillStatus);
457 }
458 }
459 // this was constructed using TColgp_Array1OfPnt
aec37c15 460 else
ac04d101 461 {
ceae62f0
A
462 Standard_Integer aSize = mypolyg.Size();
463 TColgp_Array1OfPnt aPolyg(1, aSize);
464 for(Standard_Integer anIndex = 1; anIndex <= aSize; ++anIndex)
ac04d101 465 {
ceae62f0 466 aPolyg.SetValue(anIndex, mypolyg.Pnt(anIndex-1));
ac04d101
SA
467 }
468 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, aPolyg, myFillStatus);
469 }
470
471 if(HasLocation())
aec37c15 472 aNewEntity->SetLocation(Location());
ac04d101
SA
473
474 aNewEntity->UpdateLocation(theLocation);
475
476 return aNewEntity;
477}
478
479//=======================================================================
480//function : Project
aec37c15 481//purpose :
ac04d101
SA
482//=======================================================================
483
ceae62f0 484void Select3D_SensitiveCircle::Project(const Handle_Select3D_Projector &aProjector)
329843e2 485{
aec37c15 486 Select3D_SensitivePoly::Project(aProjector);
329843e2
A
487 gp_Pnt2d aCenter;
488 aProjector->Project(myCenter3D, aCenter);
489 myCenter2D = aCenter;
490}
491
ac04d101
SA
492//=======================================================================
493//function : ComputeCenter3D
aec37c15 494//purpose :
ac04d101
SA
495//=======================================================================
496
ceae62f0 497void Select3D_SensitiveCircle::ComputeCenter3D()
329843e2 498{
ceae62f0
A
499 gp_XYZ aCenter;
500 Standard_Integer nbpoints = mypolyg.Size();
501 if (nbpoints != 1)
329843e2
A
502 {
503 // The mass of points system
ceae62f0 504 Standard_Integer aMass = nbpoints - 1;
329843e2 505 // Find the circle barycenter
ceae62f0 506 for (Standard_Integer anIndex = 0; anIndex < nbpoints-1; ++anIndex)
329843e2 507 {
ceae62f0 508 aCenter += mypolyg.Pnt(anIndex);
329843e2
A
509 }
510 myCenter3D = aCenter / aMass;
511 }
ac04d101
SA
512 else
513 {
ceae62f0 514 myCenter3D = mypolyg.Pnt(0);
329843e2
A
515 }
516}