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
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.
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.
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.
21 // Modified Tue Apr 14 1998 by rob : fix Bug : Case of Null Radius Circle...
23 #include <Select3D_SensitiveCircle.ixx>
24 #include <Precision.hxx>
25 #include <gp_Lin2d.hxx>
27 #include <CSLib_Class2d.hxx>
28 #include <Select3D_SensitiveTriangle.hxx>
30 #include <Select3D_Pnt.hxx>
31 #include <Select3D_Pnt2d.hxx>
32 #include <Select3D_Projector.hxx>
35 static Standard_Integer S3D_GetCircleNBPoints(const Handle(Geom_Circle)& C,
36 const Standard_Integer anInputNumber)
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)
44 if (C->Radius()>Precision::Confusion())
45 return 2*anInputNumber+1;
46 // The radius is too small and circle degenerates into point
50 static Standard_Integer S3D_GetArcNBPoints(const Handle(Geom_Circle)& C,
51 const Standard_Integer anInputNumber)
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())
57 return 2*anInputNumber-1;
59 // The radius is too small and circle degenerates into point
63 //=======================================================================
64 //function : Select3D_SensitiveCircle (constructor)
65 //purpose : Definition of a sensitive circle
66 //=======================================================================
68 Select3D_SensitiveCircle::
69 Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
70 const Handle(Geom_Circle)& TheCircle,
71 const Standard_Boolean FilledCircle,
72 const Standard_Integer NbPoints):
73 Select3D_SensitivePoly(OwnerId, S3D_GetCircleNBPoints(TheCircle,NbPoints)),
74 myFillStatus(FilledCircle),
79 if (mypolyg.Size() != 1)
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;
88 for(Standard_Integer anIndex=1;anIndex<=NbPoints;anIndex++)
90 TheCircle->D1(curu,p1,v1);
93 mypolyg.SetPnt(rank-1, p1);
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);
98 mypolyg.SetPnt(rank-1, p2);
103 // Copy the first point to the last point of mypolyg
104 mypolyg.SetPnt(NbPoints*2, mypolyg.Pnt(0));
106 myCenter3D = TheCircle->Location();
111 mypolyg.SetPnt(0, TheCircle->Location());
113 myCenter3D = mypolyg.Pnt(0);
117 //=======================================================================
118 //function : Select3D_SensitiveCircle (constructor)
119 //purpose : Definition of a sensitive arc
120 //=======================================================================
122 Select3D_SensitiveCircle::
123 Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
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):
129 Select3D_SensitivePoly(OwnerId, S3D_GetArcNBPoints(TheCircle,NbPoints)),
130 myFillStatus(FilledCircle),
135 if (mypolyg.Size() != 1)
146 Standard_Real du = (myend-mystart)/(NbPoints-1);
147 Standard_Real R = TheCircle->Radius();
148 Standard_Integer rank = 1;
149 Standard_Real curu = mystart;
151 for(Standard_Integer anIndex=1;anIndex<=NbPoints-1;anIndex++)
153 TheCircle->D1(curu,p1,v1);
155 mypolyg.SetPnt(rank-1, p1);
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);
160 mypolyg.SetPnt(rank-1, p2);
164 TheCircle->D0(myend,p1);
165 mypolyg.SetPnt(NbPoints*2-2, p1);
167 myCenter3D = TheCircle->Location();
171 mypolyg.SetPnt(0, TheCircle->Location());
173 myCenter3D = mypolyg.Pnt(0);
177 //=======================================================================
178 //function : Select3D_SensitiveCircle
180 //=======================================================================
182 Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
183 const Handle(TColgp_HArray1OfPnt)& Thepolyg3d,
184 const Standard_Boolean FilledCircle):
185 Select3D_SensitivePoly(OwnerId, Thepolyg3d),
186 myFillStatus(FilledCircle),
190 if (mypolyg.Size() != 1)
193 myCenter3D = mypolyg.Pnt(0);
196 //=======================================================================
197 //function : Select3D_SensitiveCircle
199 //=======================================================================
201 Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
202 const TColgp_Array1OfPnt& Thepolyg3d,
203 const Standard_Boolean FilledCircle):
204 Select3D_SensitivePoly(OwnerId, Thepolyg3d),
205 myFillStatus(FilledCircle),
209 if (mypolyg.Size() != 1)
212 myCenter3D = mypolyg.Pnt(0);
215 //=======================================================================
218 //=======================================================================
220 Standard_Boolean Select3D_SensitiveCircle::Matches (const SelectBasics_PickArgs& thePickArgs,
221 Standard_Real& theMatchDMin,
222 Standard_Real& theMatchDepth)
224 Standard_Integer aSize = mypolyg.Size();
225 Standard_Integer aDetectedIndex = -1;
226 gp_XY aPickXY (thePickArgs.X(), thePickArgs.Y());
229 Standard_Boolean Found = Standard_False;
230 Standard_Integer anIndex = 0;
234 while(anIndex < aSize-2 && !Found)
236 Standard_Integer TheStat =
237 Select3D_SensitiveTriangle::Status(mypolyg.Pnt2d(anIndex),
238 mypolyg.Pnt2d(anIndex+1),
239 mypolyg.Pnt2d(anIndex+2),
240 aPickXY, thePickArgs.Tolerance(),
242 Found = (TheStat != 2);
245 aDetectedIndex = anIndex;
253 Standard_Real Xmin,Ymin,Xmax,Ymax;
255 // Get coordinates of the bounding box
256 Bnd_Box2d(mybox2d).Get(Xmin,Ymin,Xmax,Ymax);
257 TColgp_Array1OfPnt2d anArrayOf2dPnt(1, aSize);
259 // Fill anArrayOf2dPnt with points from mypolig2d
260 Points2D(anArrayOf2dPnt);
262 CSLib_Class2d anInOutTool (anArrayOf2dPnt,
263 thePickArgs.Tolerance(),
264 thePickArgs.Tolerance(),
265 Xmin, Ymin, Xmax, Ymax);
267 // Method SiDans returns the status :
268 // 1 - the point is inside the circle
269 // 0 - the point is on the circle
270 // -1 - the point is outside the circle
271 Standard_Integer aStat = anInOutTool.SiDans (gp_Pnt2d (aPickXY));
274 // Compute DMin (a distance between the center and the point)
275 theMatchDMin = gp_XY (myCenter2D.x - aPickXY.X(), myCenter2D.y - aPickXY.Y()).Modulus();
277 theMatchDepth = ComputeDepth (thePickArgs.PickLine(), aDetectedIndex);
279 return !thePickArgs.IsClipped (theMatchDepth);
282 return Standard_False;
287 theMatchDepth = ComputeDepth (thePickArgs.PickLine(), aDetectedIndex);
289 return !thePickArgs.IsClipped (theMatchDepth);
292 return Standard_False;
295 // Circle degenerates into point
296 theMatchDMin = gp_Pnt2d(aPickXY).Distance(mypolyg.Pnt2d(0));
297 if (theMatchDMin <= thePickArgs.Tolerance() * SensitivityFactor())
299 theMatchDepth = ComputeDepth (thePickArgs.PickLine(), aDetectedIndex);
301 return !thePickArgs.IsClipped (theMatchDepth);
304 return Standard_False;
307 //=======================================================================
310 //=======================================================================
312 Standard_Boolean Select3D_SensitiveCircle::
313 Matches(const Standard_Real XMin,
314 const Standard_Real YMin,
315 const Standard_Real XMax,
316 const Standard_Real YMax,
317 const Standard_Real aTol)
320 abox.Update(Min(XMin,XMax),Min(YMin,YMax),Max(XMin,XMax),Max(YMin,YMax));
323 for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();anIndex++)
325 if(abox.IsOut(mypolyg.Pnt2d(anIndex)))
326 return Standard_False;
328 return Standard_True;
331 //=======================================================================
334 //=======================================================================
336 Standard_Boolean Select3D_SensitiveCircle::
337 Matches (const TColgp_Array1OfPnt2d& aPoly,
338 const Bnd_Box2d& aBox,
339 const Standard_Real aTol)
341 Standard_Real Umin,Vmin,Umax,Vmax;
342 aBox.Get(Umin,Vmin,Umax,Vmax);
343 CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
345 for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();++anIndex)
347 Standard_Integer RES = aClassifier2d.SiDans(mypolyg.Pnt2d(anIndex));
349 return Standard_False;
351 return Standard_True;
354 //=======================================================================
355 //function : ArrayBounds
357 //=======================================================================
359 void Select3D_SensitiveCircle::
360 ArrayBounds(Standard_Integer & Low,
361 Standard_Integer & Up) const
364 Up = mypolyg.Size()-1;
367 //=======================================================================
368 //function : GetPoint3d
370 //=======================================================================
372 gp_Pnt Select3D_SensitiveCircle::
373 GetPoint3d(const Standard_Integer Rank) const
375 if(Rank>=0 && Rank<mypolyg.Size())
376 return mypolyg.Pnt(Rank);
381 //=======================================================================
384 //=======================================================================
386 void Select3D_SensitiveCircle::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
388 Standard_Integer aSize = mypolyg.Size();
390 S<<"\tSensitiveCircle 3D :";
392 Standard_Boolean isclosed = 1== aSize;
394 S<<"(Closed Circle)"<<endl;
396 S<<"(Arc Of Circle)"<<endl;
399 S<<"\t\tExisting Location"<<endl;
404 gp_XYZ aCenter = myCenter3D;
405 Standard_Real R = (aCenter-mypolyg.Pnt(0)).Modulus();
407 S<<"\t\t Center : ("<<aCenter.X()<<" , "<<aCenter.Y()<<" , "<<aCenter.Z()<<" )"<<endl;
408 S<<"\t\t Radius :"<<R<<endl;
412 //=======================================================================
413 //function : ComputeDepth
415 //=======================================================================
417 Standard_Real Select3D_SensitiveCircle::ComputeDepth (const gp_Lin& thePickLine,
418 const Standard_Integer theDetectedIndex) const
421 if (theDetectedIndex == -1)
427 aCDG += mypolyg.Pnt (theDetectedIndex);
428 aCDG += mypolyg.Pnt (theDetectedIndex + 1);
429 aCDG += mypolyg.Pnt (theDetectedIndex + 2);
433 return ElCLib::Parameter (thePickLine, gp_Pnt (aCDG));
436 //=======================================================================
437 //function : GetConnected
439 //=======================================================================
441 Handle(Select3D_SensitiveEntity) Select3D_SensitiveCircle::GetConnected(const TopLoc_Location& theLocation)
443 // Create a copy of this
444 Handle(Select3D_SensitiveEntity) aNewEntity;
445 // this was constructed using Handle(Geom_Circle)
446 if(!myCircle.IsNull())
448 if((myend-mystart) > Precision::Confusion())
451 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, myCircle, mystart, myend, myFillStatus);
456 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, myCircle, myFillStatus);
459 // this was constructed using TColgp_Array1OfPnt
462 Standard_Integer aSize = mypolyg.Size();
463 TColgp_Array1OfPnt aPolyg(1, aSize);
464 for(Standard_Integer anIndex = 1; anIndex <= aSize; ++anIndex)
466 aPolyg.SetValue(anIndex, mypolyg.Pnt(anIndex-1));
468 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, aPolyg, myFillStatus);
472 aNewEntity->SetLocation(Location());
474 aNewEntity->UpdateLocation(theLocation);
479 //=======================================================================
482 //=======================================================================
484 void Select3D_SensitiveCircle::Project(const Handle_Select3D_Projector &aProjector)
486 Select3D_SensitivePoly::Project(aProjector);
488 aProjector->Project(myCenter3D, aCenter);
489 myCenter2D = aCenter;
492 //=======================================================================
493 //function : ComputeCenter3D
495 //=======================================================================
497 void Select3D_SensitiveCircle::ComputeCenter3D()
500 Standard_Integer nbpoints = mypolyg.Size();
503 // The mass of points system
504 Standard_Integer aMass = nbpoints - 1;
505 // Find the circle barycenter
506 for (Standard_Integer anIndex = 0; anIndex < nbpoints-1; ++anIndex)
508 aCenter += mypolyg.Pnt(anIndex);
510 myCenter3D = aCenter / aMass;
514 myCenter3D = mypolyg.Pnt(0);