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),
80 if (mypolyg.Size() != 1)
84 Standard_Real ustart = TheCircle->FirstParameter(),uend = TheCircle->LastParameter();
85 Standard_Real du = (uend-ustart)/NbPoints;
86 Standard_Real R = TheCircle->Radius();
87 Standard_Integer rank = 1;
88 Standard_Real curu =ustart;
89 for(Standard_Integer anIndex=1;anIndex<=NbPoints;anIndex++)
91 TheCircle->D1(curu,p1,v1);
94 mypolyg.SetPnt(rank-1, p1);
96 p2 = gp_Pnt(p1.X()+v1.X()*tan(du/2.)*R,
97 p1.Y()+v1.Y()*tan(du/2.)*R,
98 p1.Z()+v1.Z()*tan(du/2.)*R);
99 mypolyg.SetPnt(rank-1, p2);
104 // Copy the first point to the last point of mypolyg
105 mypolyg.SetPnt(NbPoints*2, mypolyg.Pnt(0));
107 myCenter3D = TheCircle->Location();
112 mypolyg.SetPnt(0, TheCircle->Location());
114 myCenter3D = mypolyg.Pnt(0);
118 //=======================================================================
119 //function : Select3D_SensitiveCircle (constructor)
120 //purpose : Definition of a sensitive arc
121 //=======================================================================
123 Select3D_SensitiveCircle::
124 Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
125 const Handle(Geom_Circle)& TheCircle,
126 const Standard_Real u1,
127 const Standard_Real u2,
128 const Standard_Boolean FilledCircle,
129 const Standard_Integer NbPoints):
130 Select3D_SensitivePoly(OwnerId, S3D_GetArcNBPoints(TheCircle,NbPoints)),
131 myFillStatus(FilledCircle),
137 if (mypolyg.Size() != 1)
148 Standard_Real du = (myend-mystart)/(NbPoints-1);
149 Standard_Real R = TheCircle->Radius();
150 Standard_Integer rank = 1;
151 Standard_Real curu = mystart;
153 for(Standard_Integer anIndex=1;anIndex<=NbPoints-1;anIndex++)
155 TheCircle->D1(curu,p1,v1);
157 mypolyg.SetPnt(rank-1, p1);
159 p2 = gp_Pnt(p1.X()+v1.X()*tan(du/2.)*R,
160 p1.Y()+v1.Y()*tan(du/2.)*R,
161 p1.Z()+v1.Z()*tan(du/2.)*R);
162 mypolyg.SetPnt(rank-1, p2);
166 TheCircle->D0(myend,p1);
167 mypolyg.SetPnt(NbPoints*2-2, p1);
169 myCenter3D = TheCircle->Location();
173 mypolyg.SetPnt(0, TheCircle->Location());
175 myCenter3D = mypolyg.Pnt(0);
179 //=======================================================================
180 //function : Select3D_SensitiveCircle
182 //=======================================================================
184 Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
185 const Handle(TColgp_HArray1OfPnt)& Thepolyg3d,
186 const Standard_Boolean FilledCircle):
187 Select3D_SensitivePoly(OwnerId, Thepolyg3d),
188 myFillStatus(FilledCircle),
193 if (mypolyg.Size() != 1)
196 myCenter3D = mypolyg.Pnt(0);
199 //=======================================================================
200 //function : Select3D_SensitiveCircle
202 //=======================================================================
204 Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectBasics_EntityOwner)& OwnerId,
205 const TColgp_Array1OfPnt& Thepolyg3d,
206 const Standard_Boolean FilledCircle):
207 Select3D_SensitivePoly(OwnerId, Thepolyg3d),
208 myFillStatus(FilledCircle),
213 if (mypolyg.Size() != 1)
216 myCenter3D = mypolyg.Pnt(0);
219 //=======================================================================
222 //=======================================================================
224 Standard_Boolean Select3D_SensitiveCircle::
225 Matches(const Standard_Real X,
226 const Standard_Real Y,
227 const Standard_Real aTol,
230 Standard_Integer aSize = mypolyg.Size();
233 Standard_Boolean Found = Standard_False;
234 Standard_Integer anIndex = 0;
238 while(anIndex < aSize-2 && !Found)
240 Standard_Integer TheStat =
241 Select3D_SensitiveTriangle::Status(mypolyg.Pnt2d(anIndex),
242 mypolyg.Pnt2d(anIndex+1),
243 mypolyg.Pnt2d(anIndex+2),
244 gp_XY(X,Y),aTol,DMin);
245 Found = (TheStat != 2);
246 if(Found) myDetectedIndex = 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,aTol,aTol,Xmin,Ymin,Xmax,Ymax);
264 // Method SiDans returns the status :
265 // 1 - the point is inside the circle
266 // 0 - the point is on the circle
267 // -1 - the point is outside the circle
268 Standard_Integer aStat = anInOutTool.SiDans(gp_Pnt2d(X,Y));
271 // Compute DMin (a distance between the center and the point)
272 DMin = gp_XY(myCenter2D.x - X, myCenter2D.y - Y).Modulus();
273 Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
274 return Standard_True;
276 return Standard_False;
281 Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
284 // Circle degenerates into point
285 DMin = gp_Pnt2d(X, Y).Distance(mypolyg.Pnt2d(0));
286 if (DMin <= aTol*SensitivityFactor())
287 return Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
289 return Standard_False;
292 //=======================================================================
295 //=======================================================================
297 Standard_Boolean Select3D_SensitiveCircle::
298 Matches(const Standard_Real XMin,
299 const Standard_Real YMin,
300 const Standard_Real XMax,
301 const Standard_Real YMax,
302 const Standard_Real aTol)
306 abox.Update(Min(XMin,XMax),Min(YMin,YMax),Max(XMin,XMax),Max(YMin,YMax));
309 for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();anIndex++)
311 if(abox.IsOut(mypolyg.Pnt2d(anIndex)))
312 return Standard_False;
314 return Standard_True;
317 //=======================================================================
320 //=======================================================================
322 Standard_Boolean Select3D_SensitiveCircle::
323 Matches (const TColgp_Array1OfPnt2d& aPoly,
324 const Bnd_Box2d& aBox,
325 const Standard_Real aTol)
327 myDetectedIndex = -1;
328 Standard_Real Umin,Vmin,Umax,Vmax;
329 aBox.Get(Umin,Vmin,Umax,Vmax);
330 CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
332 for(Standard_Integer anIndex=0;anIndex<mypolyg.Size();++anIndex)
334 Standard_Integer RES = aClassifier2d.SiDans(mypolyg.Pnt2d(anIndex));
336 return Standard_False;
338 return Standard_True;
341 //=======================================================================
342 //function : ArrayBounds
344 //=======================================================================
346 void Select3D_SensitiveCircle::
347 ArrayBounds(Standard_Integer & Low,
348 Standard_Integer & Up) const
351 Up = mypolyg.Size()-1;
354 //=======================================================================
355 //function : GetPoint3d
357 //=======================================================================
359 gp_Pnt Select3D_SensitiveCircle::
360 GetPoint3d(const Standard_Integer Rank) const
362 if(Rank>=0 && Rank<mypolyg.Size())
363 return mypolyg.Pnt(Rank);
368 //=======================================================================
371 //=======================================================================
373 void Select3D_SensitiveCircle::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
375 Standard_Integer aSize = mypolyg.Size();
377 S<<"\tSensitiveCircle 3D :";
379 Standard_Boolean isclosed = 1== aSize;
381 S<<"(Closed Circle)"<<endl;
383 S<<"(Arc Of Circle)"<<endl;
386 S<<"\t\tExisting Location"<<endl;
391 gp_XYZ aCenter = myCenter3D;
392 Standard_Real R = (aCenter-mypolyg.Pnt(0)).Modulus();
394 S<<"\t\t Center : ("<<aCenter.X()<<" , "<<aCenter.Y()<<" , "<<aCenter.Z()<<" )"<<endl;
395 S<<"\t\t Radius :"<<R<<endl;
399 //=======================================================================
400 //function : ComputeDepth
402 //=======================================================================
404 Standard_Real Select3D_SensitiveCircle::ComputeDepth(const gp_Lin& EyeLine) const
407 if(myDetectedIndex==-1)
413 aCDG += mypolyg.Pnt(myDetectedIndex);
414 aCDG += mypolyg.Pnt(myDetectedIndex+1);
415 aCDG += mypolyg.Pnt(myDetectedIndex+2);
418 return ElCLib::Parameter(EyeLine,gp_Pnt(aCDG));
421 //=======================================================================
422 //function : GetConnected
424 //=======================================================================
426 Handle(Select3D_SensitiveEntity) Select3D_SensitiveCircle::GetConnected(const TopLoc_Location& theLocation)
428 // Create a copy of this
429 Handle(Select3D_SensitiveEntity) aNewEntity;
430 // this was constructed using Handle(Geom_Circle)
431 if(!myCircle.IsNull())
433 if((myend-mystart) > Precision::Confusion())
436 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, myCircle, mystart, myend, myFillStatus);
441 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, myCircle, myFillStatus);
444 // this was constructed using TColgp_Array1OfPnt
447 Standard_Integer aSize = mypolyg.Size();
448 TColgp_Array1OfPnt aPolyg(1, aSize);
449 for(Standard_Integer anIndex = 1; anIndex <= aSize; ++anIndex)
451 aPolyg.SetValue(anIndex, mypolyg.Pnt(anIndex-1));
453 aNewEntity = new Select3D_SensitiveCircle(myOwnerId, aPolyg, myFillStatus);
457 aNewEntity->SetLocation(Location());
459 aNewEntity->UpdateLocation(theLocation);
464 //=======================================================================
467 //=======================================================================
469 void Select3D_SensitiveCircle::Project(const Handle_Select3D_Projector &aProjector)
471 Select3D_SensitivePoly::Project(aProjector);
473 aProjector->Project(myCenter3D, aCenter);
474 myCenter2D = aCenter;
477 //=======================================================================
478 //function : ComputeCenter3D
480 //=======================================================================
482 void Select3D_SensitiveCircle::ComputeCenter3D()
485 Standard_Integer nbpoints = mypolyg.Size();
488 // The mass of points system
489 Standard_Integer aMass = nbpoints - 1;
490 // Find the circle barycenter
491 for (Standard_Integer anIndex = 0; anIndex < nbpoints-1; ++anIndex)
493 aCenter += mypolyg.Pnt(anIndex);
495 myCenter3D = aCenter / aMass;
499 myCenter3D = mypolyg.Pnt(0);