acce87a425ec312b9ec0b259aa928694682e31d0
[occt.git] / src / Select3D / Select3D_SensitiveTriangulation.cxx
1 // File:        Select3D_SensitiveTriangulation.cxx
2 // Created:     Thu May 15 17:47:05 1997
3 // Author:      Robert COUBLANC
4 //              <rob@robox.paris1.matra-dtv.fr>
5 //Modified      Thur Apr 09 98 by rob : No more computation of free edges.
6 //                                      fix bug on Compute Depth (don't forget
7 //                                      Location...)
8
9 #define BUC60858        //GG 27/03/01 Avoid to crash when selecting
10 //                      a triangle containing confused or aligned points.
11
12 #include <Select3D_SensitiveTriangulation.ixx>
13 #include <gp_Pnt2d.hxx>
14 #include <Poly_Connect.hxx>
15 #include <CSLib_Class2d.hxx>
16 #include <TColStd_Array1OfInteger.hxx>
17 #include <Select3D_SensitiveTriangle.hxx>
18 #include <Precision.hxx>
19 #include <ElCLib.hxx>
20 #include <CSLib_Class2d.hxx>
21
22
23 static Standard_Integer S3D_NumberOfFreeEdges(const Handle(Poly_Triangulation)& Trg)
24 {
25   Standard_Integer nFree = 0;
26   Poly_Connect pc(Trg);
27   Standard_Integer t[3];
28   Standard_Integer i,j;
29   for (i = 1; i <= Trg->NbTriangles(); i++) {
30     pc.Triangles(i,t[0],t[1],t[2]);
31     for (j = 0; j < 3; j++)
32       if (t[j] == 0) nFree++;
33   }
34   return nFree; 
35 }
36 static Standard_Boolean S3D_STriangul_NearSegment (const gp_XY& p0, const gp_XY& p1, const gp_XY& TheP,
37                                                    const Standard_Real aTol, Standard_Real& aDMin)
38 {
39   Bnd_Box2d B;
40   B.SetVoid();
41   B.Set(p0);
42   B.Update(p1.X(),p1.Y());
43   B.Enlarge(aTol*3);
44   if(B.IsOut(TheP)) return Standard_False;
45
46   gp_XY V01(p1);V01-=p0;
47   gp_XY Vec(TheP);Vec -= p0;
48   
49   Standard_Real u = Vec*V01.Normalized();
50   if(u<-aTol) return Standard_False;
51   Standard_Real u1 = u-aTol;
52   Standard_Real modmod = V01.SquareModulus();
53   if(u1*u1> modmod) return Standard_False;
54
55   gp_XY N01 (-V01.Y(),V01.X());
56   N01.Normalize();
57   aDMin = Abs (Vec * N01);
58   return aDMin <= aTol;
59 }
60
61 // static Standard_Real S3D_SquareDistanceFromEdge(gp_Pnt2d PCur,
62 //                                              gp_Pnt2d PEdg1,
63 //                                              gp_Pnt2d PEdg2,
64 //                                              const Standard_Real TolTol)
65 // {
66 //   gp_XY VEdg (PEdg1.XY());
67 //   gp_XY VCur (PEdg1.XY());
68 //   VEdg-= PEdg2.XY();
69 //   VCur-=PCur.XY();
70 //   Standard_Real long1 = VEdg.SquareModulus();
71   
72 //   if(long1<=TolTol)
73 //     return VCur.SquareModulus();
74 //   Standard_Real Val = VEdg^VCur;
75 //   return Val*Val/long1;
76   
77 // }
78
79 static Standard_Boolean S3D_IsEdgeIn(const Standard_Integer e1,
80                                      const Standard_Integer e2,
81                                      const Standard_Integer N1,
82                                      const Standard_Integer N2,
83                                      const Standard_Integer N3)
84 {
85   Standard_Integer bid1  = (e1 == N1) ? N1 : ((e1 == N2) ? N2 : ( e1==N3 ? N3 : 0));
86   if(bid1==0) return Standard_False;
87   Standard_Integer bid2  = (e2 == N1) ? N1 : ((e2 == N2) ? N2 : ( e2==N3 ? N3 : 0));
88
89   if(bid2==0 || bid2 ==bid1) return Standard_False;
90   return Standard_True;
91 }
92
93
94
95 //=======================================================================
96 //function : Select3D_SensitiveTriangulation
97 //purpose  : 
98 //=======================================================================
99
100 Select3D_SensitiveTriangulation::
101 Select3D_SensitiveTriangulation(const Handle(SelectBasics_EntityOwner)& OwnerId,
102                                 const Handle(Poly_Triangulation)& Trg,
103                                 const TopLoc_Location& Loc,
104                                 const Standard_Boolean InteriorFlag):
105                                 Select3D_SensitiveEntity(OwnerId),
106 myTriangul(Trg),
107 myiniloc(Loc),
108 myIntFlag(InteriorFlag),
109 myNodes2d(1,Trg->NbNodes()),
110 myDetectedTr(-1)
111 {
112   // Code honteusement vole a DBRep_DrawableShape::Display...
113   // calcul des edges libres et du cdg 3d de la triangulation:
114   // Ce code devrait, pour plus de facilites etre integre dans la poly_triangulation...
115
116   Standard_Integer fr = 1;
117   const Poly_Array1OfTriangle& triangles = myTriangul->Triangles();
118   const TColgp_Array1OfPnt& Nodes = myTriangul->Nodes();  
119   Standard_Integer nbTriangles (myTriangul->NbTriangles());
120   gp_XYZ cdg(0,0,0);
121   Standard_Integer n[3];
122   
123   // pour rechercher les connexions dans le cas ou on ne s'occupe de la frontiere...
124   if(!myIntFlag){
125     myFreeEdges = new TColStd_HArray1OfInteger(1,2*S3D_NumberOfFreeEdges(Trg));
126     TColStd_Array1OfInteger& FreeE = myFreeEdges->ChangeArray1();
127     Poly_Connect pc(myTriangul);
128     Standard_Integer t[3];
129     Standard_Integer i,j;
130     for ( i = 1; i <= nbTriangles; i++) {
131       pc.Triangles(i,t[0],t[1],t[2]);
132       triangles(i).Get(n[0],n[1],n[2]);
133       cdg += (Nodes(n[0]).XYZ() + Nodes(n[1]).XYZ()+ Nodes(n[2]).XYZ())/3.;
134       for (j = 0; j < 3; j++) {
135         Standard_Integer k = (j+1) % 3;
136         if (t[j] == 0) {
137           FreeE(fr)  = n[j];
138           FreeE(fr+1)= n[k];
139           fr += 2;
140         }
141       }
142     }
143   }
144   else{
145     for (Standard_Integer i = 1; i <= nbTriangles; i++) {
146       triangles(i).Get(n[0],n[1],n[2]);
147       cdg += (Nodes(n[0]).XYZ() + Nodes(n[1]).XYZ()+ Nodes(n[2]).XYZ())/3.;
148     }
149   }
150
151   
152   if(nbTriangles!=0) cdg /= nbTriangles;
153   myCDG3D = gp_Pnt(cdg);
154   
155   ComputeTotalTrsf();
156
157   if(myTrsf.Form()!=gp_Identity)
158     myCDG3D.Transform(myTrsf);
159 }
160
161
162 //=======================================================================
163 //function : Select3D_SensitiveTriangulation
164 //purpose  : 
165 //=======================================================================
166 Select3D_SensitiveTriangulation::
167 Select3D_SensitiveTriangulation(const Handle(SelectBasics_EntityOwner)& OwnerId,
168                                 const Handle(Poly_Triangulation)& Trg,
169                                 const TopLoc_Location& Loc,
170                                 const Handle(TColStd_HArray1OfInteger)& FreeEdges,
171                                 const gp_Pnt& TheCDG,
172                                 const Standard_Boolean InteriorFlag):
173 Select3D_SensitiveEntity(OwnerId),
174 myTriangul(Trg),
175 myiniloc(Loc),
176 myCDG3D(TheCDG),
177 myFreeEdges(FreeEdges),
178 myIntFlag(InteriorFlag),
179 myNodes2d(1,Trg->NbNodes()),
180 myDetectedTr(-1)
181 {
182 }
183 //=======================================================================
184 //function : Project
185 //purpose  : 
186 //=======================================================================
187
188 void Select3D_SensitiveTriangulation::Project(const Select3D_Projector& aPrj) 
189 {
190   Select3D_SensitiveEntity::Project(aPrj); // to set the field last proj...
191   
192   mybox2d.SetVoid();
193   const TColgp_Array1OfPnt& Nodes = myTriangul->Nodes();  
194   
195   gp_Pnt2d ProjPT;
196   
197   for(Standard_Integer I=1;I<=myTriangul->NbNodes();I++){
198     if(myTrsf.Form()!=gp_Identity)
199       aPrj.Project(Nodes(I).Transformed(myTrsf),ProjPT);
200     else
201       aPrj.Project(Nodes(I),ProjPT);
202     
203     myNodes2d.SetValue(I,ProjPT);
204     mybox2d.Add(ProjPT);
205   }
206   
207   aPrj.Project(myCDG3D,myCDG2D);
208 }
209
210 //=======================================================================
211 //function : Areas
212 //purpose  : 
213 //=======================================================================
214
215 void Select3D_SensitiveTriangulation::Areas(SelectBasics_ListOfBox2d& boxes) 
216 {
217   boxes.Append(mybox2d);
218 }
219
220 //=======================================================================
221 //function : getUV
222 //purpose  : compute parameters of the picked point on triangle in 2d
223 //     Note: parameters of point P on triangle (P1, P2, P3) are defined 
224 //           as U and V such that P = P1 + U * (P2 - P1) + V * (P3 - P1);
225 //    Range: U >= 0, V >= 0, U + V <= 1
226 //=======================================================================
227
228 static gp_XY getUV (const gp_XY& aP2d1, const gp_XY& aP2d2, const gp_XY& aP2d3,
229                     const gp_XY& aPick)
230 {
231   gp_XY aDU = aP2d2 - aP2d1;
232   gp_XY aDV = aP2d3 - aP2d1;
233   Standard_Real aDet = aDU ^ aDV;
234
235   // case of non-degenerated triangle
236   gp_XY aDP = aPick - aP2d1;
237   if ( Abs (aDet) > gp::Resolution() )
238   {
239     Standard_Real aU =  (aDP ^ aDV) / aDet;
240     Standard_Real aV = -(aDP ^ aDU) / aDet;
241     if ( aU < 0. ) aU = 0.;
242     if ( aV < 0. ) aV = 0.;
243     if ( aU + aV > 1. ) { Standard_Real aD = aU + aV; aU /= aD; aV /= aD; }
244     return gp_XY (aU, aV);
245   }
246
247   // degenerated case (in 2d projection)
248   Standard_Real aL2U = aDU.SquareModulus();
249   Standard_Real aL2V = aDV.SquareModulus();
250   if ( aL2U < gp::Resolution() ) // side 1-2 is degenerated 
251   {
252     if ( aL2V < gp::Resolution() ) // whole triangle is degenerated to point
253       return gp_XY (0., 0.);
254     else
255       return gp_XY (0., (aDP * aDV) / aL2V);
256   }
257   else if ( aL2V < gp::Resolution() ) // side 1-3 is degenerated
258     return gp_XY ((aDP * aDU) / aL2U, 0.);
259   else // sides 1-2 and 1-3 are collinear
260   {
261     // select parameter on one of sides so as to have points closer to picked
262     Standard_Real aU = Min (1., Max (0., (aDP * aDU) / aL2U));
263     Standard_Real aV = Min (1., Max (0., (aDP * aDV) / aL2V));
264     gp_XY aP2dU = aP2d1 + aU * aDU;
265     gp_XY aP2dV = aP2d1 + aV * aDV;
266     if ( (aPick - aP2dU).SquareModulus() < (aPick - aP2dV).SquareModulus() )
267       return gp_XY ((aDP * aDU) / aL2U, 0.);
268     else
269       return gp_XY (0., (aDP * aDV) / aL2V);
270   }
271 }
272
273 //=======================================================================
274 //function : Matches
275 //purpose  : 
276 //=======================================================================
277 Standard_Boolean Select3D_SensitiveTriangulation::Matches(const Standard_Real X,
278                                                           const Standard_Real Y,
279                                                           const Standard_Real aTol,
280                                                           Standard_Real& DMin) 
281 {
282   // get view direction (necessary for calculation of depth) from field mylastprj of the base class
283   if ( ! mylastprj )
284     return Standard_False;
285
286   DMin = Precision::Infinite();
287   gp_XY BidPoint(X,Y);
288   myDetectedTr = -1;
289   const Poly_Array1OfTriangle& triangles = myTriangul->Triangles();
290
291   // on regarde si on est a l'interieur d'1 triangle 2d.
292   if(myIntFlag)
293   {
294     gp_Lin EyeLine = (*((Select3D_Projector*)mylastprj)).Shoot(X,Y);
295     if ( myTrsf.Form()!=gp_Identity )
296       EyeLine.Transform (myTrsf.Inverted());
297
298     Standard_Real aMinDepth = Precision::Infinite();
299     const TColgp_Array1OfPnt& Nodes = myTriangul->Nodes();  
300     for (Standard_Integer itr=1; itr<=myTriangul->NbTriangles(); itr++)
301     {
302       Standard_Integer n1,n2,n3;
303       triangles(itr).Get(n1,n2,n3);
304       const gp_XY& aPnt2d1 = myNodes2d(n1).XY();
305       const gp_XY& aPnt2d2 = myNodes2d(n2).XY();
306       const gp_XY& aPnt2d3 = myNodes2d(n3).XY();
307       Standard_Real DD = 0.;
308       if (Status (BidPoint, aPnt2d1, aPnt2d2, aPnt2d3, aTol, DD) == 2)
309         continue;
310
311       // compute depth on this triangle
312       gp_XY aUV = getUV (aPnt2d1, aPnt2d2, aPnt2d3, BidPoint);
313       Standard_Real aDepth1 = ElCLib::Parameter (EyeLine, Nodes(n1));
314       Standard_Real aDepth2 = ElCLib::Parameter (EyeLine, Nodes(n2));
315       Standard_Real aDepth3 = ElCLib::Parameter (EyeLine, Nodes(n3));
316       Standard_Real aDepth = aDepth1 + aUV.X() * (aDepth2 - aDepth1) + 
317                                        aUV.Y() * (aDepth3 - aDepth1);
318
319       // take triangle with lowest depth
320       if ( aDepth < aMinDepth )
321       {
322         aMinDepth = aDepth;
323         myDetectedTr = itr;
324         DMin = DD;
325       }
326     }
327   }
328   
329   //    Cas Uniquement Test sur Frontiere de la triangulation...
330   //   
331   else
332   {
333     //Standard_Integer ifirst;
334     TColStd_Array1OfInteger& FreeE = myFreeEdges->ChangeArray1();
335     Standard_Integer nn = FreeE.Length(), Node1,Node2;
336     //Standard_Real LEdg;
337     //Standard_Real DMinDMin,TolTol = aTol*aTol;
338     
339     for (Standard_Integer ifri =1; ifri <= nn && myDetectedTr < 0; ifri+=2)
340     {
341       Node1 = FreeE(ifri);
342       Node2 = FreeE(ifri+1);
343       if (S3D_STriangul_NearSegment (myNodes2d(Node1).XY(),
344                                      myNodes2d(Node2).XY(),
345                                      BidPoint, aTol, DMin) )
346       {
347         for(Standard_Integer itr=1; itr <= myTriangul->NbTriangles(); itr++)
348         {
349           Standard_Integer n1,n2,n3;
350           triangles(itr).Get(n1,n2,n3);
351           if(S3D_IsEdgeIn(Node1,Node2,n1,n2,n3))
352           {
353             myDetectedTr = itr;
354             break; // return first found; selection of closest is not implemented yet
355           }
356         }
357       }
358     }
359   } 
360   if ( myDetectedTr <= 0 )
361     return Standard_False;
362   Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
363   return Standard_True;
364 }
365
366
367 //=======================================================================
368 //function : Matches
369 //purpose  : 
370 //=======================================================================
371
372 Standard_Boolean Select3D_SensitiveTriangulation::Matches(const Standard_Real XMin,
373                                                           const Standard_Real YMin,
374                                                           const Standard_Real XMax,
375                                                           const Standard_Real YMax,
376                                                           const Standard_Real aTol) 
377 {
378   Bnd_Box2d B;
379   B.Update(Min(XMin,XMax)-aTol,
380            Min(YMin,YMax)-aTol,
381            Max(XMin,XMax)+aTol,
382            Max(YMin,YMax)+aTol);
383   
384   for(Standard_Integer i=myNodes2d.Lower();i<=myNodes2d.Upper();i++){
385     if(B.IsOut(myNodes2d(i)))
386       return Standard_False;
387   }
388   return Standard_True;
389 }
390
391
392 //=======================================================================
393 //function : Matches
394 //purpose  : 
395 //=======================================================================
396
397 Standard_Boolean Select3D_SensitiveTriangulation::
398 Matches (const TColgp_Array1OfPnt2d& aPoly,
399          const Bnd_Box2d& aBox,
400          const Standard_Real aTol)
401
402   Standard_Real Umin,Vmin,Umax,Vmax;
403   aBox.Get(Umin,Vmin,Umax,Vmax);
404   Standard_Real Tolu,Tolv;
405   Tolu = 1e-7;
406   Tolv = 1e-7;
407   CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
408
409   for(Standard_Integer j=1;j<=myNodes2d.Length();j++){
410     Standard_Integer RES = aClassifier2d.SiDans(myNodes2d(j));
411     if(RES!=1) return Standard_False;
412   }
413   return Standard_True;
414 }
415
416
417
418 Standard_Integer Select3D_SensitiveTriangulation::Status (const gp_XY& TheP,
419                                                           const gp_XY& Proj0,
420                                                           const gp_XY& Proj1,
421                                                           const gp_XY& Proj2,
422                                                           const Standard_Real aTol,
423                                                           Standard_Real& DD) const
424 {
425   return Select3D_SensitiveTriangle::Status(Proj0,Proj1,Proj2,TheP,aTol,DD);
426 }
427
428 //=======================================================================
429 //function : IsFree
430 //purpose  : 
431 //=======================================================================
432
433 Standard_Boolean Select3D_SensitiveTriangulation::IsFree(const Standard_Integer IndexOfTriangle,
434                                                          Standard_Integer& FoundIndex) const
435 {
436
437   FoundIndex=-1;
438   Standard_Integer n[3];
439   const Poly_Array1OfTriangle& triangles = myTriangul->Triangles();
440   triangles(IndexOfTriangle).Get(n[0],n[1],n[2]);
441     TColStd_Array1OfInteger& FreeE = myFreeEdges->ChangeArray1();
442
443   for(Standard_Integer I=1;I<=FreeE.Length() && FoundIndex==-1;I+=2){
444     
445     if(FreeE(I) == n[0]){
446       
447       if(FreeE(I+1)== n[1] || FreeE(I+1)== n[2]) FoundIndex=I;}
448     else if(FreeE(I) == n[1]){
449       if(FreeE(I+1)== n[0] || FreeE(I+1)== n[2]) FoundIndex=I;}
450     else if(FreeE(I) == n[2]){
451       if(FreeE(I+1)== n[0] || FreeE(I+1)== n[1]) FoundIndex=I;}
452   }
453   
454   return FoundIndex!=-1;
455 }
456
457
458 //=======================================================================
459 //function : GetConnected
460 //purpose  : 
461 //=======================================================================
462 Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangulation::
463 GetConnected(const TopLoc_Location& aLoc)
464 {
465   
466   Handle(Select3D_SensitiveTriangulation) NiouEnt = 
467     new Select3D_SensitiveTriangulation(myOwnerId,myTriangul,myiniloc,myFreeEdges,myCDG3D,myIntFlag);
468   
469   if(HasLocation()) NiouEnt->SetLocation(Location());
470 //  TopLoc_Location TheLocToApply = HasLocation() ?  Location()*aLoc : aLoc;
471 //  if(!TheLocToApply.IsIdentity())
472   NiouEnt->UpdateLocation(aLoc);
473     
474
475   return NiouEnt;
476 }
477
478
479 //=======================================================================
480 //function : ResetLocation
481 //purpose  : 
482 //=======================================================================
483 void Select3D_SensitiveTriangulation::ResetLocation() 
484 {
485   Select3D_SensitiveEntity::ResetLocation();
486   ComputeTotalTrsf();
487 }
488 void Select3D_SensitiveTriangulation::SetLocation(const TopLoc_Location& aLoc)
489 {
490   Select3D_SensitiveEntity::SetLocation(aLoc);
491   ComputeTotalTrsf();
492 }
493
494
495 //=======================================================================
496 //function : Dump
497 //purpose  : 
498 //=======================================================================
499 void Select3D_SensitiveTriangulation::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const 
500 {
501   S<<"\tSensitiveTriangulation 3D :"<<endl;
502   if(myiniloc.IsIdentity())
503     S<<"\t\tNo Initial Location"<<endl;
504   else
505     S<<"\t\tExisting Initial Location"<<endl;
506   if(HasLocation())
507     S<<"\t\tExisting Location"<<endl;
508   
509   S<<"\t\tNb Triangles : "<<myTriangul->NbTriangles()<<endl;
510   S<<"\t\tNb Nodes     : "<<myTriangul->NbNodes()<<endl;
511   S<<"\t\tNb Free Edges: "<<myFreeEdges->Length()/2<<endl;
512
513   if(FullDump){
514 //    S<<"\t\t\tOwner:"<<myOwnerId<<endl;
515     Select3D_SensitiveEntity::DumpBox(S,mybox2d);
516   }
517 }
518
519 //=======================================================================
520 //function : ComputeDepth
521 //purpose  :  
522 //=======================================================================
523 Standard_Real Select3D_SensitiveTriangulation::ComputeDepth(const gp_Lin& EyeLine) const
524 {
525   if(myDetectedTr==-1) return Precision::Infinite(); // non implemente actuellement...
526   const Poly_Array1OfTriangle& triangles = myTriangul->Triangles();
527   const TColgp_Array1OfPnt& Nodes = myTriangul->Nodes();  
528   
529   Standard_Integer n1,n2,n3;
530   triangles(myDetectedTr).Get(n1,n2,n3);
531   gp_Pnt P[3]={Nodes(n1),Nodes(n2),Nodes(n3)};
532
533   if(myTrsf.Form()!=gp_Identity){
534     for(Standard_Integer i =0;i<=2;i++){
535       P[i].Transform(myTrsf);
536     }
537   }
538   
539   // formule calcul du parametre du point sur l'intersection
540   // t = (P1P2 ^P1P3)* OP1  / ((P1P2^P1P3)*Dir)
541   Standard_Real prof(Precision::Infinite());
542   gp_Pnt Oye  = EyeLine.Location(); // origine de la ligne oeil/point vise...
543   gp_Dir Dir  = EyeLine.Direction();
544
545   gp_Vec Vtr[3]; 
546   for(Standard_Integer i=0;i<=2;i++)
547     Vtr[i] = gp_Vec(P[i%3],P[(i+1)%3]);
548   Vtr[2] = -Vtr[2];
549   
550   // eliminons tout de suite les cas singuliers...
551   Standard_Integer SingularCase(-1);
552   if(Vtr[0].SquareMagnitude()<= Precision::Confusion())
553     SingularCase = 0;
554   if(Vtr[1].SquareMagnitude()<= Precision::Confusion())
555     SingularCase = (SingularCase == -1) ? 1 : 2;
556 #ifdef BUC60858
557   if(Vtr[2].SquareMagnitude()<= Precision::Confusion())
558     if( SingularCase < 0 ) SingularCase = 1;
559 #endif
560   
561   // 3 pts confondus...
562   if(SingularCase ==2){
563     prof= ElCLib::Parameter(EyeLine,P[0]);
564     return prof;
565   }
566   
567   if(SingularCase!=0)
568     Vtr[0].Normalize();
569   if(SingularCase!=1 &&
570      SingularCase!=2)
571     Vtr[2].Normalize();
572   gp_Vec OPo(Oye,P[0]);
573   // 2 points confondus... on recherche l'intersection entre le segment et la ligne oeil/point vise.
574   // 
575   if(SingularCase!=-1){
576     gp_Vec V = SingularCase==0 ? Vtr[2] : Vtr[0];
577     gp_Vec Det = Dir^V;
578     gp_Vec VSM = OPo^V;
579     if(Det.X()> Precision::Confusion())
580       prof = VSM.X()/Det.X();
581     else if (Det.Y()> Precision::Confusion())
582       prof = VSM.Y()/Det.Y();
583     else if(Det.Z()> Precision::Confusion())
584       prof = VSM.Z()/Det.Z();
585   }
586   else{
587     
588     Standard_Real val1 = OPo.DotCross(Vtr[0],Vtr[2]);
589     Standard_Real val2 = Dir.DotCross(Vtr[0],Vtr[2]);
590     
591     if(Abs(val2)>Precision::Confusion())
592       prof =val1/val2;
593   } 
594   if (prof==Precision::Infinite()){
595     prof= ElCLib::Parameter(EyeLine,P[0]);
596     prof = Min (prof, ElCLib::Parameter(EyeLine,P[1]));
597     prof = Min (prof, ElCLib::Parameter(EyeLine,P[2]));
598   }
599   
600   return prof;
601 }
602
603 //=======================================================================
604 //function : DetectedTriangle
605 //purpose  : 
606 //=======================================================================
607 Standard_Boolean Select3D_SensitiveTriangulation::DetectedTriangle(gp_Pnt& P1,
608                                                                    gp_Pnt& P2,
609                                                                    gp_Pnt& P3) const
610 {
611   if(myDetectedTr==-1) return Standard_False; // non implemente actuellement...
612   const Poly_Array1OfTriangle& triangles = myTriangul->Triangles();
613   const TColgp_Array1OfPnt& Nodes = myTriangul->Nodes();  
614   Standard_Integer n1,n2,n3;
615   triangles(myDetectedTr).Get(n1,n2,n3);
616   
617   P1 = Nodes(n1);
618   P2 = Nodes(n2);
619   P3 = Nodes(n3);
620   if(myTrsf.Form()!=gp_Identity){
621     P1.Transform(myTrsf);
622     P2.Transform(myTrsf);
623     P3.Transform(myTrsf);
624   }
625   
626   return Standard_True;
627 }
628
629 //=============================================================================
630 // Function : DetectedTriangle2d
631 // Purpose  : 
632 //=============================================================================
633 Standard_Boolean Select3D_SensitiveTriangulation::DetectedTriangle2d( 
634   gp_Pnt2d& P1, gp_Pnt2d& P2, gp_Pnt2d& P3) const
635 {
636   if(myDetectedTr==-1) 
637     return Standard_False; // non implemente actuellement...
638   const Poly_Array1OfTriangle& triangles = myTriangul->Triangles();
639   const TColgp_Array1OfPnt& Nodes = myTriangul->Nodes();  
640   Standard_Integer n1,n2,n3;
641   triangles( myDetectedTr ).Get(n1,n2,n3);
642
643   int aLower = myNodes2d.Lower();
644   int anUpper = myNodes2d.Upper();
645   if ( n1 >= aLower && n1 <= anUpper && 
646        n2 >= aLower && n2 <= anUpper &&
647        n3 >= aLower && n3 <= anUpper )
648   {
649     P1 = myNodes2d.Value( n1 );
650     P2 = myNodes2d.Value( n2 );
651     P3 = myNodes2d.Value( n3 );
652     return Standard_True;
653   }
654   else 
655     return Standard_False;
656   
657 }
658
659 void Select3D_SensitiveTriangulation::ComputeTotalTrsf() 
660 {
661   Standard_Boolean hasloc = (HasLocation() || !myiniloc.IsIdentity());
662   
663   if(hasloc){
664     if(myiniloc.IsIdentity())
665       myTrsf = Location().Transformation();
666     else if(HasLocation()){
667       myTrsf = (Location()*myiniloc).Transformation();
668     }
669     else
670       myTrsf = myiniloc.Transformation();
671   }
672   else{
673     gp_Trsf TheId;
674     myTrsf = TheId;
675   }
676 }