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