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