1 // File: Select3D_SensitiveTriangle.cxx
2 // Created: Wed May 14 16:56:06 1997
3 // Author: Robert COUBLANC
4 // <rob@robox.paris1.matra-dtv.fr>
7 #include <Select3D_SensitiveTriangle.ixx>
10 #include <SelectBasics_BasicTool.hxx>
11 #include <gp_Pnt2d.hxx>
13 #include <gp_Dir2d.hxx>
14 #include <Precision.hxx>
15 #include <Bnd_Box.hxx>
17 #include <TopLoc_Location.hxx>
19 #include <CSLib_Class2d.hxx>
21 static Standard_Boolean S3D_Str_NearSegment (const gp_XY& p0, const gp_XY& p1, const gp_XY& TheP,
22 const Standard_Real aTol, Standard_Real& aDMin)
30 Standard_Real u = Vec*V01.Normalized();
31 if(u<-aTol) return Standard_False;
32 Standard_Real u1 = u-aTol;
33 Standard_Real modmod = V01.SquareModulus();
34 if(u1*u1> modmod) return Standard_False;
36 gp_XY N01 (-V01.Y(),V01.X());
38 aDMin = Abs (Vec * N01);
42 //==================================================
45 //==================================================
47 Select3D_SensitiveTriangle::
48 Select3D_SensitiveTriangle(const Handle(SelectBasics_EntityOwner)& OwnerId,
52 const Select3D_TypeOfSensitivity aType):
53 Select3D_SensitivePoly(OwnerId,3),
56 mypolyg.SetPnt(0, P0);
57 mypolyg.SetPnt(1, P1);
58 mypolyg.SetPnt(2, P2);
61 //==================================================
64 //==================================================
66 Standard_Boolean Select3D_SensitiveTriangle::
67 Matches(const Standard_Real X,
68 const Standard_Real Y,
69 const Standard_Real aTol,
72 Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
73 if(Bnd_Box2d(mybox2d).IsOut(gp_Pnt2d(X,Y))) return Standard_False;
78 case Select3D_TOS_BOUNDARY:
79 Res = Status(X,Y,aTol,DMin);
82 case Select3D_TOS_INTERIOR:
83 Res = Status(X,Y,aTol,DMin);
84 return (Res==0 || Res == 1);
93 //==================================================
96 //==================================================
98 Standard_Boolean Select3D_SensitiveTriangle::
99 Matches (const Standard_Real XMin,
100 const Standard_Real YMin,
101 const Standard_Real XMax,
102 const Standard_Real YMax,
103 const Standard_Real aTol)
106 B.Update(Min(XMin,XMax)-aTol,
109 Max(YMin,YMax)+aTol);
110 for(Standard_Integer anIndex=0;anIndex<=2;++anIndex)
112 if(B.IsOut(mypolyg.Pnt2d(anIndex)))
113 return Standard_False;
115 return Standard_True;
118 //=======================================================================
121 //=======================================================================
123 Standard_Boolean Select3D_SensitiveTriangle::
124 Matches (const TColgp_Array1OfPnt2d& aPoly,
125 const Bnd_Box2d& aBox,
126 const Standard_Real aTol)
128 Standard_Real Umin,Vmin,Umax,Vmax;
129 aBox.Get(Umin,Vmin,Umax,Vmax);
130 Standard_Real Tolu,Tolv;
133 CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
135 for(Standard_Integer anIndex=0;anIndex<=2;++anIndex)
137 Standard_Integer RES = aClassifier2d.SiDans(mypolyg.Pnt2d(anIndex));
139 return Standard_False;
141 return Standard_True;
144 //==================================================
145 // Function: Points3D
147 //==================================================
149 void Select3D_SensitiveTriangle::Points3D(gp_Pnt& P0,gp_Pnt& P1,gp_Pnt& P2) const
156 //==================================================
157 // Function: Center3D
159 //==================================================
161 gp_Pnt Select3D_SensitiveTriangle::Center3D() const
163 gp_XYZ aPnt1, aPnt2, aPnt3;
164 aPnt1 = mypolyg.Pnt(0);
165 aPnt2 = mypolyg.Pnt(1);
166 aPnt3 = mypolyg.Pnt(2);
167 return gp_Pnt((aPnt1+aPnt2+aPnt3)/3.);
170 //==================================================
171 // Function: Center2D
173 //==================================================
175 gp_XY Select3D_SensitiveTriangle::Center2D() const
177 gp_XY aPnt1, aPnt2, aPnt3;
178 aPnt1 = mypolyg.Pnt2d(0);
179 aPnt2 = mypolyg.Pnt2d(1);
180 aPnt3 = mypolyg.Pnt2d(2);
181 return (aPnt1+aPnt2+aPnt3)/3.;
184 //=======================================================================
186 //purpose : 0 = inside /1 = Boundary/ 2 = outside
187 //=======================================================================
189 Standard_Integer Select3D_SensitiveTriangle::Status(const Standard_Real X,
190 const Standard_Real Y,
191 const Standard_Real aTol,
192 Standard_Real& DMin) const
194 return Status(mypolyg.Pnt2d(0), mypolyg.Pnt2d(1), mypolyg.Pnt2d(2),
195 gp_XY(X,Y), aTol, DMin);
198 //=======================================================================
201 //=======================================================================
203 Standard_Integer Select3D_SensitiveTriangle::Status(const gp_XY& p0,
207 const Standard_Real aTol,
211 B.Update(p0.X(),p0.Y());B.Update(p1.X(),p1.Y());B.Update(p2.X(),p2.Y());
213 if(B.IsOut(TheP)) return 2;
215 // the point is classified corresponding to demi-spaces limited
216 // by each side of the triangle (with tolerance)
217 gp_XY V01(p1);V01-=p0;
218 gp_XY V02(p2);V02-=p0;
219 gp_XY V12(p2);V12-=p1;
221 // check these particular cases...
222 // if one of vectors is almost null (2 points are mixed),
223 // leave at once (it is already in the bounding box, which is good...)
227 if ( V01.SquareModulus() <= gp::Resolution() )
229 Standard_Real LV = V02.SquareModulus();
230 if ( LV <= gp::Resolution())
231 return 0; // 3 points are mixed, and TheP is in the bounding box B...
233 if ( S3D_Str_NearSegment (p0, p2, TheP, aTol, DMin) )
237 if ( V02.SquareModulus() <= gp::Resolution() )
239 if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
243 if ( V12.SquareModulus() <= gp::Resolution() )
245 if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
249 if ( V01.CrossMagnitude(V02) <= gp::Resolution() )
251 if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
256 // oriented normal to p0p1...
257 gp_Dir2d N (-V01.Y(), V01.X());
258 Standard_Boolean Neg = (N * V02 < 0.);
265 Standard_Real aD1 = Vec * N.XY();
269 // oriented normal to p1p2...
271 N.SetCoord(p2.Y()-p1.Y(),p1.X()-p2.X());
273 N.SetCoord(p1.Y()-p2.Y(),p2.X()-p1.X());
275 Vec.SetCoord(TheP.X()-p1.X(),TheP.Y()-p1.Y());
276 Standard_Real aD2 = Vec * N.XY();
280 // oriented normal to p2p0...
281 // attention v20 (x0-x2) => N y2-y0 => -N y0-y2
282 // (y0-y2) x0-x2 x2-x0
284 N.SetCoord(p0.Y()-p2.Y(),p2.X()-p0.X());
286 N.SetCoord(p2.Y()-p0.Y(),p0.X()-p2.X());
288 Vec.SetCoord(TheP.X()-p2.X(),TheP.Y()-p2.Y());
289 Standard_Real aD3 = Vec * N.XY();
293 // compute 2d distance to triangle
294 Standard_Real aD = Min (aD1, Min (aD2, aD3));
295 DMin = ( aD < 0 ? -aD : 0. );
299 //=======================================================================
302 //=======================================================================
304 void Select3D_SensitiveTriangle::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
306 // general information....
308 S<<"\tSensitiveTriangle 3D :\n";
310 S<<"\t\tExisting Location"<<endl;
312 gp_Pnt aPnt1, aPnt2, aPnt3;
313 aPnt1 = mypolyg.Pnt(0);
314 aPnt2 = mypolyg.Pnt(1);
315 aPnt3 = mypolyg.Pnt(2);
316 S<<"\t\t P0 [ "<<aPnt1.X()<<" , "<<aPnt1.Y()<<" , "<<aPnt1.Z()<<" ]"<<endl;
317 S<<"\t\t P1 [ "<<aPnt2.X()<<" , "<<aPnt2.Y()<<" , "<<aPnt2.Z()<<" ]"<<endl;
318 S<<"\t\t P2 [ "<<aPnt3.X()<<" , "<<aPnt3.Y()<<" , "<<aPnt3.Z()<<" ]"<<endl;
322 S<<"\t\tProjected Points"<<endl;
324 gp_Pnt2d aPnt1, aPnt2, aPnt3;
325 aPnt1 = mypolyg.Pnt2d(0);
326 aPnt2 = mypolyg.Pnt2d(1);
327 aPnt3 = mypolyg.Pnt2d(2);
328 S<<"\t\t 0.[ "<<aPnt1.X()<<" , "<<aPnt1.Y()<<" ]"<<endl;
329 S<<"\t\t 1.[ "<<aPnt2.X()<<" , "<<aPnt2.Y()<<" ]"<<endl;
330 S<<"\t\t 2.[ "<<aPnt3.X()<<" , "<<aPnt3.Y()<<" ]"<<endl;
331 Select3D_SensitiveEntity::DumpBox(S,mybox2d);
335 //=======================================================================
336 //function : ComputeDepth
338 //=======================================================================
340 Standard_Real Select3D_SensitiveTriangle::ComputeDepth(const gp_Lin& EyeLine) const
342 Standard_Real prof(Precision::Infinite());
351 TheTrsf = Location().Transformation();
353 if(TheTrsf.Form()!=gp_Identity)
355 P1.Transform(TheTrsf);
356 P2.Transform(TheTrsf);
357 P3.Transform(TheTrsf);
360 // formula calculation of the point parameters on intersection
361 // t = (P1P2 ^P1P3)* OP1 / ((P1P2^P1P3)*Dir)
363 gp_Pnt Oye = EyeLine.Location(); // origin of the target line eye/point...
364 gp_Dir Dir = EyeLine.Direction();
366 gp_Vec P1P2 (P1,P2), P1P3(P1,P3);
371 Standard_Real val1 = oP1.DotCross(P1P2,P1P3);
372 Standard_Real val2 = Dir.DotCross(P1P2,P1P3);
374 if(Abs(val2)>Precision::Confusion())
377 if (prof==Precision::Infinite())
379 prof= ElCLib::Parameter(EyeLine,P1);
380 prof = Min (prof, ElCLib::Parameter(EyeLine,P2));
381 prof = Min (prof, ElCLib::Parameter(EyeLine,P3));
386 //==================================================
387 // Function: GetConnected
389 //==================================================
391 Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangle::
392 GetConnected(const TopLoc_Location &theLocation)
394 // Create a copy of this
395 Handle(Select3D_SensitiveEntity) aNewEntity =
396 new Select3D_SensitiveTriangle(myOwnerId, mypolyg.Pnt(0), mypolyg.Pnt(1), mypolyg.Pnt(2), mytype);
399 aNewEntity->SetLocation(Location());
401 aNewEntity->UpdateLocation(theLocation);