0022922: Clean up warnings on uninitialized / unused variables
[occt.git] / src / Select3D / Select3D_SensitiveTriangle.cxx
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>
5
6
7 #include <Select3D_SensitiveTriangle.ixx>
8
9
10 #include <SelectBasics_BasicTool.hxx>
11 #include <gp_Pnt2d.hxx>
12 #include <gp_Pnt.hxx>
13 #include <gp_Dir2d.hxx>
14 #include <Precision.hxx>
15 #include <Bnd_Box.hxx>
16 #include <ElCLib.hxx>
17 #include <TopLoc_Location.hxx>
18
19 #include <CSLib_Class2d.hxx>
20
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)
23 {
24   gp_XY V01(p1);
25   V01 -= p0;
26
27   gp_XY Vec(TheP);
28   Vec -= p0;
29   
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;
35
36   gp_XY N01 (-V01.Y(),V01.X());
37   N01.Normalize();
38   aDMin = Abs (Vec * N01);
39   return aDMin <= aTol;
40 }
41
42 //==================================================
43 // Function: Creation
44 // Purpose :
45 //==================================================
46
47 Select3D_SensitiveTriangle::
48 Select3D_SensitiveTriangle(const Handle(SelectBasics_EntityOwner)& OwnerId,
49                            const gp_Pnt& P0,
50                            const gp_Pnt& P1,
51                            const gp_Pnt& P2,
52                            const Select3D_TypeOfSensitivity aType):
53 Select3D_SensitivePoly(OwnerId,3),
54 mytype (aType)
55 {
56   mypolyg.SetPnt(0, P0);
57   mypolyg.SetPnt(1, P1);
58   mypolyg.SetPnt(2, P2);
59 }
60
61 //==================================================
62 // Function: Matches
63 // Purpose :
64 //==================================================
65
66 Standard_Boolean Select3D_SensitiveTriangle::
67 Matches(const Standard_Real X, 
68         const Standard_Real Y, 
69         const Standard_Real aTol, 
70         Standard_Real& DMin)
71 {
72   Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
73   if(Bnd_Box2d(mybox2d).IsOut(gp_Pnt2d(X,Y))) return Standard_False;
74
75   Standard_Integer Res;
76   switch (mytype)
77   {
78   case Select3D_TOS_BOUNDARY:
79     Res = Status(X,Y,aTol,DMin);
80     return Res== 1;
81     break;
82   case Select3D_TOS_INTERIOR:
83     Res = Status(X,Y,aTol,DMin);
84     return (Res==0 || Res == 1);
85 #ifndef DEB
86   default:
87     break;
88 #endif
89   }
90   return Standard_True;
91 }
92
93 //==================================================
94 // Function: Matches
95 // Purpose :
96 //==================================================
97
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)
104 {
105   Bnd_Box2d B;
106   B.Update(Min(XMin,XMax)-aTol,
107            Min(YMin,YMax)-aTol,
108            Max(XMin,XMax)+aTol,
109            Max(YMin,YMax)+aTol);
110   for(Standard_Integer anIndex=0;anIndex<=2;++anIndex)
111   {
112     if(B.IsOut(mypolyg.Pnt2d(anIndex)))
113       return Standard_False;
114   }
115   return Standard_True;
116 }
117
118 //=======================================================================
119 //function : Matches
120 //purpose  : 
121 //=======================================================================
122
123 Standard_Boolean Select3D_SensitiveTriangle::
124 Matches (const TColgp_Array1OfPnt2d& aPoly,
125          const Bnd_Box2d& aBox,
126          const Standard_Real aTol)
127 {
128   Standard_Real Umin,Vmin,Umax,Vmax;
129   aBox.Get(Umin,Vmin,Umax,Vmax);
130   Standard_Real Tolu,Tolv;
131   Tolu = 1e-7;
132   Tolv = 1e-7;
133   CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
134
135   for(Standard_Integer anIndex=0;anIndex<=2;++anIndex)
136   {
137     Standard_Integer RES = aClassifier2d.SiDans(mypolyg.Pnt2d(anIndex));
138     if(RES!=1)
139       return Standard_False;
140   }
141   return Standard_True;
142 }
143
144 //==================================================
145 // Function: Points3D
146 // Purpose :
147 //==================================================
148
149 void Select3D_SensitiveTriangle::Points3D(gp_Pnt& P0,gp_Pnt& P1,gp_Pnt& P2) const
150 {
151   P0 = mypolyg.Pnt(0);
152   P1 = mypolyg.Pnt(1);
153   P2 = mypolyg.Pnt(2);
154 }
155
156 //==================================================
157 // Function: Center3D
158 // Purpose :
159 //==================================================
160
161 gp_Pnt Select3D_SensitiveTriangle::Center3D() const
162 {
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.);
168 }
169
170 //==================================================
171 // Function: Center2D
172 // Purpose :
173 //==================================================
174
175 gp_XY Select3D_SensitiveTriangle::Center2D() const
176 {
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.;
182 }
183
184 //=======================================================================
185 //function : Status
186 //purpose  : 0 = inside /1 = Boundary/ 2 = outside
187 //=======================================================================
188
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
193 {
194   return Status(mypolyg.Pnt2d(0), mypolyg.Pnt2d(1), mypolyg.Pnt2d(2),
195                 gp_XY(X,Y), aTol, DMin);
196 }
197
198 //=======================================================================
199 //function : Status
200 //purpose  : 
201 //=======================================================================
202
203 Standard_Integer  Select3D_SensitiveTriangle::Status(const gp_XY& p0,
204                                                      const gp_XY& p1,
205                                                      const gp_XY& p2,
206                                                      const gp_XY& TheP,
207                                                      const Standard_Real aTol,
208                                                      Standard_Real& DMin)
209 {
210   Bnd_Box2d B;
211   B.Update(p0.X(),p0.Y());B.Update(p1.X(),p1.Y());B.Update(p2.X(),p2.Y());
212   B.Enlarge(aTol);
213   if(B.IsOut(TheP)) return 2;
214   
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;
220
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...)
224   
225   DMin = aTol;
226   
227   if ( V01.SquareModulus() <= gp::Resolution() )
228   {
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...
232
233     if ( S3D_Str_NearSegment (p0, p2, TheP, aTol, DMin) )
234       return 0;
235     return 2;    
236   }
237   if ( V02.SquareModulus() <= gp::Resolution() )
238   {
239     if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
240       return 0;
241     return 2;
242   }
243   if ( V12.SquareModulus() <= gp::Resolution() )
244   {
245     if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
246       return 0;
247     return 2;
248   }
249   if ( V01.CrossMagnitude(V02) <= gp::Resolution() )
250   {
251     if ( S3D_Str_NearSegment (p0, p1, TheP, aTol, DMin) )
252       return 0;
253     return 2;
254   }
255
256   // oriented normal to p0p1...
257   gp_Dir2d N (-V01.Y(), V01.X()); 
258   Standard_Boolean Neg = (N * V02 < 0.);
259   if ( Neg ) 
260     N.Reverse();
261
262   gp_XY Vec(TheP);
263   Vec -= p0;
264   
265   Standard_Real aD1 = Vec * N.XY();
266   if ( aD1 < -aTol ) 
267     return 2;
268
269   // oriented normal to p1p2...
270   if(Neg)
271     N.SetCoord(p2.Y()-p1.Y(),p1.X()-p2.X());
272   else
273     N.SetCoord(p1.Y()-p2.Y(),p2.X()-p1.X());
274   
275   Vec.SetCoord(TheP.X()-p1.X(),TheP.Y()-p1.Y());
276   Standard_Real aD2 = Vec * N.XY();
277   if ( aD2 < -aTol ) 
278     return 2;   // outside
279
280   // oriented normal to p2p0...
281   // attention v20 (x0-x2)    =>   N y2-y0   => -N  y0-y2
282   //               (y0-y2)           x0-x2          x2-x0
283   if(Neg)
284     N.SetCoord(p0.Y()-p2.Y(),p2.X()-p0.X());
285   else
286     N.SetCoord(p2.Y()-p0.Y(),p0.X()-p2.X());
287   
288   Vec.SetCoord(TheP.X()-p2.X(),TheP.Y()-p2.Y());
289   Standard_Real aD3 = Vec * N.XY();
290   if ( aD3 < -aTol ) 
291     return 2;  // outside
292
293   // compute 2d distance to triangle
294   Standard_Real aD = Min (aD1, Min (aD2, aD3));
295   DMin = ( aD < 0 ? -aD : 0. );
296   return 0;
297 }
298
299 //=======================================================================
300 //function : Dump
301 //purpose  : 
302 //=======================================================================
303
304 void Select3D_SensitiveTriangle::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const 
305 {
306   // general information....
307
308   S<<"\tSensitiveTriangle 3D :\n";
309   if(HasLocation())
310     S<<"\t\tExisting Location"<<endl;
311
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;
319
320   if(FullDump) 
321   {
322     S<<"\t\tProjected Points"<<endl;
323
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);
332   }
333 }
334
335 //=======================================================================
336 //function : ComputeDepth
337 //purpose  : 
338 //=======================================================================
339
340 Standard_Real Select3D_SensitiveTriangle::ComputeDepth(const gp_Lin& EyeLine) const
341 {
342   Standard_Real prof(Precision::Infinite());
343
344   gp_Pnt P1, P2, P3;
345   P1 = mypolyg.Pnt(0);
346   P2 = mypolyg.Pnt(1);
347   P3 = mypolyg.Pnt(2);
348
349   gp_Trsf TheTrsf ;
350   if(HasLocation()) 
351     TheTrsf = Location().Transformation();
352   
353   if(TheTrsf.Form()!=gp_Identity) 
354   {
355     P1.Transform(TheTrsf);
356     P2.Transform(TheTrsf);
357     P3.Transform(TheTrsf);
358   }
359   
360   // formula calculation of the point parameters on intersection
361   // t = (P1P2 ^P1P3)* OP1  / ((P1P2^P1P3)*Dir)
362   
363   gp_Pnt Oye  = EyeLine.Location(); // origin of the target line eye/point...
364   gp_Dir Dir  = EyeLine.Direction();
365   
366   gp_Vec P1P2 (P1,P2), P1P3(P1,P3);
367   P1P2.Normalize();
368   P1P3.Normalize();
369   
370   gp_Vec oP1(Oye,P1);
371   Standard_Real val1 = oP1.DotCross(P1P2,P1P3);
372   Standard_Real val2 = Dir.DotCross(P1P2,P1P3);
373   
374   if(Abs(val2)>Precision::Confusion())
375     prof =val1/val2;
376   
377   if (prof==Precision::Infinite()) 
378   {
379     prof= ElCLib::Parameter(EyeLine,P1);
380     prof = Min (prof, ElCLib::Parameter(EyeLine,P2));
381     prof = Min (prof, ElCLib::Parameter(EyeLine,P3));
382   }
383   return prof;
384 }
385
386 //==================================================
387 // Function: GetConnected
388 // Purpose :
389 //==================================================
390
391 Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangle::
392 GetConnected(const TopLoc_Location &theLocation) 
393 {
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);
397
398   if (HasLocation()) 
399     aNewEntity->SetLocation(Location()); 
400
401   aNewEntity->UpdateLocation(theLocation);
402
403   return aNewEntity;
404 }