Merge OCC22357 and replacing french comments by english one
[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.hxx>
15 #include <Poly_Connect.hxx>
16 #include <CSLib_Class2d.hxx>
17 #include <TColStd_Array1OfInteger.hxx>
18 #include <Select3D_SensitiveTriangle.hxx>
19 #include <Precision.hxx>
20 #include <ElCLib.hxx>
21 #include <CSLib_Class2d.hxx>
22
23
24 static Standard_Integer S3D_NumberOfFreeEdges(const Handle(Poly_Triangulation)& Trg)
25 {
26   Standard_Integer nFree = 0;
27   Poly_Connect pc(Trg);
28   Standard_Integer t[3];
29   Standard_Integer i,j;
30   for (i = 1; i <= Trg->NbTriangles(); i++) {
31     pc.Triangles(i,t[0],t[1],t[2]);
32     for (j = 0; j < 3; j++)
33       if (t[j] == 0) nFree++;
34   }
35   return nFree;
36 }
37 static Standard_Boolean S3D_STriangul_NearSegment (const gp_XY& p0, const gp_XY& p1, const gp_XY& TheP,
38                                                    const Standard_Real aTol, Standard_Real& aDMin)
39 {
40   Bnd_Box2d B;
41   B.SetVoid();
42   B.Set(p0);
43   B.Update(p1.X(),p1.Y());
44   B.Enlarge(aTol*3);
45   if(B.IsOut(TheP)) return Standard_False;
46
47   gp_XY V01(p1);V01-=p0;
48   gp_XY Vec(TheP);Vec -= p0;
49
50   Standard_Real u = Vec*V01.Normalized();
51   if(u<-aTol) return Standard_False;
52   Standard_Real u1 = u-aTol;
53   Standard_Real modmod = V01.SquareModulus();
54   if(u1*u1> modmod) return Standard_False;
55
56   gp_XY N01 (-V01.Y(),V01.X());
57   N01.Normalize();
58   aDMin = Abs (Vec * N01);
59   return aDMin <= aTol;
60 }
61
62 // static Standard_Real S3D_SquareDistanceFromEdge(gp_Pnt2d PCur,
63 //                                              gp_Pnt2d PEdg1,
64 //                                              gp_Pnt2d PEdg2,
65 //                                              const Standard_Real TolTol)
66 // {
67 //   gp_XY VEdg (PEdg1.XY());
68 //   gp_XY VCur (PEdg1.XY());
69 //   VEdg-= PEdg2.XY();
70 //   VCur-=PCur.XY();
71 //   Standard_Real long1 = VEdg.SquareModulus();
72
73 //   if(long1<=TolTol)
74 //     return VCur.SquareModulus();
75 //   Standard_Real Val = VEdg^VCur;
76 //   return Val*Val/long1;
77
78 // }
79
80 static Standard_Boolean S3D_IsEdgeIn(const Standard_Integer e1,
81                                      const Standard_Integer e2,
82                                      const Standard_Integer N1,
83                                      const Standard_Integer N2,
84                                      const Standard_Integer N3)
85 {
86   Standard_Integer bid1  = (e1 == N1) ? N1 : ((e1 == N2) ? N2 : ( e1==N3 ? N3 : 0));
87   if(bid1==0) return Standard_False;
88   Standard_Integer bid2  = (e2 == N1) ? N1 : ((e2 == N2) ? N2 : ( e2==N3 ? N3 : 0));
89
90   if(bid2==0 || bid2 ==bid1) return Standard_False;
91   return Standard_True;
92 }
93
94
95
96 //=======================================================================
97 //function : Select3D_SensitiveTriangulation
98 //purpose  :
99 //=======================================================================
100
101 Select3D_SensitiveTriangulation::
102 Select3D_SensitiveTriangulation(const Handle(SelectBasics_EntityOwner)& OwnerId,
103                                 const Handle(Poly_Triangulation)& Trg,
104                                 const TopLoc_Location& Loc,
105                                 const Standard_Boolean InteriorFlag):
106                                 Select3D_SensitiveEntity(OwnerId),
107 myTriangul(Trg),
108 myiniloc(Loc),
109 myIntFlag(InteriorFlag),
110 myNodes2d(1,Trg->NbNodes()),
111 myDetectedTr(-1)
112 {
113   // calculate free edges and cdg 3d of the triangulation:
114   // This code should have been integrated in 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   // to find connections in case when the border is not concerned...
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 Handle(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 : Matches
222 //purpose  :
223 //=======================================================================
224 Standard_Boolean Select3D_SensitiveTriangulation::Matches(const Standard_Real X,
225                                                           const Standard_Real Y,
226                                                           const Standard_Real aTol,
227                                                           Standard_Real& DMin)
228 {
229   // get view direction (necessary for calculation of depth) from field mylastprj of the base class
230   if (mylastprj.IsNull())
231     return Standard_False;
232
233   DMin = Precision::Infinite();
234   gp_XY BidPoint(X,Y);
235   myDetectedTr = -1;
236   const Poly_Array1OfTriangle& triangles = myTriangul->Triangles();
237
238   // it is checked if we are inside the triangle 2d.
239   if(myIntFlag)
240   {
241     gp_Lin EyeLine = mylastprj->Shoot(X,Y);
242     if ( myTrsf.Form()!=gp_Identity )
243       EyeLine.Transform (myTrsf.Inverted());
244
245     Standard_Real aMinDepth = Precision::Infinite();
246     const TColgp_Array1OfPnt& Nodes = myTriangul->Nodes();
247     for (Standard_Integer itr=1; itr<=myTriangul->NbTriangles(); itr++)
248     {
249       Standard_Integer n1,n2,n3;
250       triangles(itr).Get(n1,n2,n3);
251       const gp_XY& aPnt2d1 = myNodes2d(n1).XY();
252       const gp_XY& aPnt2d2 = myNodes2d(n2).XY();
253       const gp_XY& aPnt2d3 = myNodes2d(n3).XY();
254       gp_XY aUV;
255       Standard_Real aDistSquare = Poly::PointOnTriangle (aPnt2d1, aPnt2d2, aPnt2d3, BidPoint, aUV);
256       if ( aDistSquare > aTol * aTol )
257         continue;
258
259       // compute depth on this triangle
260       Standard_Real aDepth1 = ElCLib::Parameter (EyeLine, Nodes(n1));
261       Standard_Real aDepth2 = ElCLib::Parameter (EyeLine, Nodes(n2));
262       Standard_Real aDepth3 = ElCLib::Parameter (EyeLine, Nodes(n3));
263       Standard_Real aDepth = aDepth1 + aUV.X() * (aDepth2 - aDepth1) +
264                                        aUV.Y() * (aDepth3 - aDepth1);
265
266       // take triangle with lowest depth and within defined depth interval
267       if (aDepth < aMinDepth &&
268           aDepth > mylastprj->DepthMin() &&
269           aDepth < mylastprj->DepthMax())
270       {
271         aMinDepth = aDepth;
272         myDetectedTr = itr;
273         DMin = Sqrt (aDistSquare);
274       }
275     }
276   }
277   
278   //    Case only Test on Border of the triangulation...
279   //   
280   else
281   {
282     //Standard_Integer ifirst;
283     TColStd_Array1OfInteger& FreeE = myFreeEdges->ChangeArray1();
284     Standard_Integer nn = FreeE.Length(), Node1,Node2;
285     //Standard_Real LEdg;
286     //Standard_Real DMinDMin,TolTol = aTol*aTol;
287
288     for (Standard_Integer ifri =1; ifri <= nn && myDetectedTr < 0; ifri+=2)
289     {
290       Node1 = FreeE(ifri);
291       Node2 = FreeE(ifri+1);
292       if (S3D_STriangul_NearSegment (myNodes2d(Node1).XY(),
293                                      myNodes2d(Node2).XY(),
294                                      BidPoint, aTol, DMin) )
295       {
296         for(Standard_Integer itr=1; itr <= myTriangul->NbTriangles(); itr++)
297         {
298           Standard_Integer n1,n2,n3;
299           triangles(itr).Get(n1,n2,n3);
300           if(S3D_IsEdgeIn(Node1,Node2,n1,n2,n3))
301           {
302             myDetectedTr = itr;
303             break; // return first found; selection of closest is not implemented yet
304           }
305         }
306       }
307     }
308   }
309   if ( myDetectedTr <= 0 )
310     return Standard_False;
311
312   // compute and validate the depth (::Depth()) along the eyeline
313   return Select3D_SensitiveEntity::Matches(X,Y,aTol,DMin);
314 }
315
316
317 //=======================================================================
318 //function : Matches
319 //purpose  :
320 //=======================================================================
321
322 Standard_Boolean Select3D_SensitiveTriangulation::Matches(const Standard_Real XMin,
323                                                           const Standard_Real YMin,
324                                                           const Standard_Real XMax,
325                                                           const Standard_Real YMax,
326                                                           const Standard_Real aTol)
327 {
328   Bnd_Box2d B;
329   B.Update(Min(XMin,XMax)-aTol,
330            Min(YMin,YMax)-aTol,
331            Max(XMin,XMax)+aTol,
332            Max(YMin,YMax)+aTol);
333
334   for(Standard_Integer i=myNodes2d.Lower();i<=myNodes2d.Upper();i++){
335     if(B.IsOut(myNodes2d(i)))
336       return Standard_False;
337   }
338   return Standard_True;
339 }
340
341
342 //=======================================================================
343 //function : Matches
344 //purpose  :
345 //=======================================================================
346
347 Standard_Boolean Select3D_SensitiveTriangulation::
348 Matches (const TColgp_Array1OfPnt2d& aPoly,
349          const Bnd_Box2d& aBox,
350          const Standard_Real aTol)
351 {
352   Standard_Real Umin,Vmin,Umax,Vmax;
353   aBox.Get(Umin,Vmin,Umax,Vmax);
354   Standard_Real Tolu,Tolv;
355   Tolu = 1e-7;
356   Tolv = 1e-7;
357   CSLib_Class2d aClassifier2d(aPoly,aTol,aTol,Umin,Vmin,Umax,Vmax);
358
359   for(Standard_Integer j=1;j<=myNodes2d.Length();j++){
360     Standard_Integer RES = aClassifier2d.SiDans(myNodes2d(j));
361     if(RES!=1) return Standard_False;
362   }
363   return Standard_True;
364 }
365
366
367
368 Standard_Integer Select3D_SensitiveTriangulation::Status (const gp_XY& TheP,
369                                                           const gp_XY& Proj0,
370                                                           const gp_XY& Proj1,
371                                                           const gp_XY& Proj2,
372                                                           const Standard_Real aTol,
373                                                           Standard_Real& DD) const
374 {
375   return Select3D_SensitiveTriangle::Status(Proj0,Proj1,Proj2,TheP,aTol,DD);
376 }
377
378 //=======================================================================
379 //function : IsFree
380 //purpose  :
381 //=======================================================================
382
383 Standard_Boolean Select3D_SensitiveTriangulation::IsFree(const Standard_Integer IndexOfTriangle,
384                                                          Standard_Integer& FoundIndex) const
385 {
386
387   FoundIndex=-1;
388   Standard_Integer n[3];
389   const Poly_Array1OfTriangle& triangles = myTriangul->Triangles();
390   triangles(IndexOfTriangle).Get(n[0],n[1],n[2]);
391     TColStd_Array1OfInteger& FreeE = myFreeEdges->ChangeArray1();
392
393   for(Standard_Integer I=1;I<=FreeE.Length() && FoundIndex==-1;I+=2){
394
395     if(FreeE(I) == n[0]){
396
397       if(FreeE(I+1)== n[1] || FreeE(I+1)== n[2]) FoundIndex=I;}
398     else if(FreeE(I) == n[1]){
399       if(FreeE(I+1)== n[0] || FreeE(I+1)== n[2]) FoundIndex=I;}
400     else if(FreeE(I) == n[2]){
401       if(FreeE(I+1)== n[0] || FreeE(I+1)== n[1]) FoundIndex=I;}
402   }
403
404   return FoundIndex!=-1;
405 }
406
407
408 //=======================================================================
409 //function : GetConnected
410 //purpose  :
411 //=======================================================================
412 Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangulation::
413 GetConnected(const TopLoc_Location& aLoc)
414 {
415
416   Handle(Select3D_SensitiveTriangulation) NiouEnt =
417     new Select3D_SensitiveTriangulation(myOwnerId,myTriangul,myiniloc,myFreeEdges,myCDG3D,myIntFlag);
418
419   if(HasLocation()) NiouEnt->SetLocation(Location());
420 //  TopLoc_Location TheLocToApply = HasLocation() ?  Location()*aLoc : aLoc;
421 //  if(!TheLocToApply.IsIdentity())
422   NiouEnt->UpdateLocation(aLoc);
423
424
425   return NiouEnt;
426 }
427
428
429 //=======================================================================
430 //function : ResetLocation
431 //purpose  :
432 //=======================================================================
433 void Select3D_SensitiveTriangulation::ResetLocation()
434 {
435   Select3D_SensitiveEntity::ResetLocation();
436   ComputeTotalTrsf();
437 }
438 void Select3D_SensitiveTriangulation::SetLocation(const TopLoc_Location& aLoc)
439 {
440   Select3D_SensitiveEntity::SetLocation(aLoc);
441   ComputeTotalTrsf();
442 }
443
444
445 //=======================================================================
446 //function : Dump
447 //purpose  :
448 //=======================================================================
449 void Select3D_SensitiveTriangulation::Dump(Standard_OStream& S,const Standard_Boolean FullDump) const
450 {
451   S<<"\tSensitiveTriangulation 3D :"<<endl;
452   if(myiniloc.IsIdentity())
453     S<<"\t\tNo Initial Location"<<endl;
454   else
455     S<<"\t\tExisting Initial Location"<<endl;
456   if(HasLocation())
457     S<<"\t\tExisting Location"<<endl;
458
459   S<<"\t\tNb Triangles : "<<myTriangul->NbTriangles()<<endl;
460   S<<"\t\tNb Nodes     : "<<myTriangul->NbNodes()<<endl;
461   S<<"\t\tNb Free Edges: "<<myFreeEdges->Length()/2<<endl;
462
463   if(FullDump){
464 //    S<<"\t\t\tOwner:"<<myOwnerId<<endl;
465     Select3D_SensitiveEntity::DumpBox(S,mybox2d);
466   }
467 }
468
469 //=======================================================================
470 //function : ComputeDepth
471 //purpose  :
472 //=======================================================================
473 Standard_Real Select3D_SensitiveTriangulation::ComputeDepth(const gp_Lin& EyeLine) const
474 {
475   if(myDetectedTr==-1) return Precision::Infinite(); // currently not implemented...
476   const Poly_Array1OfTriangle& triangles = myTriangul->Triangles();
477   const TColgp_Array1OfPnt& Nodes = myTriangul->Nodes();
478
479   Standard_Integer n1,n2,n3;
480   triangles(myDetectedTr).Get(n1,n2,n3);
481   gp_Pnt P[3]={Nodes(n1),Nodes(n2),Nodes(n3)};
482
483   if(myTrsf.Form()!=gp_Identity){
484     for(Standard_Integer i =0;i<=2;i++){
485       P[i].Transform(myTrsf);
486     }
487   }
488   
489   // formula calculate the parameter of the point on the intersection
490   // t = (P1P2 ^P1P3)* OP1  / ((P1P2^P1P3)*Dir)
491   Standard_Real prof(Precision::Infinite());
492   gp_Pnt Oye  = EyeLine.Location(); // origin of the target line eye/point...
493   gp_Dir Dir  = EyeLine.Direction();
494
495   gp_Vec Vtr[3];
496   for(Standard_Integer i=0;i<=2;i++)
497     Vtr[i] = gp_Vec(P[i%3],P[(i+1)%3]);
498   Vtr[2] = -Vtr[2];
499   
500   // remove singular cases immediately...
501   Standard_Integer SingularCase(-1);
502   if(Vtr[0].SquareMagnitude()<= Precision::Confusion())
503     SingularCase = 0;
504   if(Vtr[1].SquareMagnitude()<= Precision::Confusion())
505     SingularCase = (SingularCase == -1) ? 1 : 2;
506 #ifdef BUC60858
507   if(Vtr[2].SquareMagnitude()<= Precision::Confusion())
508     if( SingularCase < 0 ) SingularCase = 1;
509 #endif
510   
511   // 3 pts mixed...
512   if(SingularCase ==2){
513     prof= ElCLib::Parameter(EyeLine,P[0]);
514     return prof;
515   }
516
517   if(SingularCase!=0)
518     Vtr[0].Normalize();
519   if(SingularCase!=1 &&
520      SingularCase!=2)
521     Vtr[2].Normalize();
522   gp_Vec OPo(Oye,P[0]);
523   // 2 points mixed... the intersection between the segment and the target line eye/point.
524   // 
525   if(SingularCase!=-1){
526     gp_Vec V = SingularCase==0 ? Vtr[2] : Vtr[0];
527     gp_Vec Det = Dir^V;
528     gp_Vec VSM = OPo^V;
529     if(Det.X()> Precision::Confusion())
530       prof = VSM.X()/Det.X();
531     else if (Det.Y()> Precision::Confusion())
532       prof = VSM.Y()/Det.Y();
533     else if(Det.Z()> Precision::Confusion())
534       prof = VSM.Z()/Det.Z();
535   }
536   else{
537
538     Standard_Real val1 = OPo.DotCross(Vtr[0],Vtr[2]);
539     Standard_Real val2 = Dir.DotCross(Vtr[0],Vtr[2]);
540
541     if(Abs(val2)>Precision::Confusion())
542       prof =val1/val2;
543   }
544   if (prof==Precision::Infinite()){
545     prof= ElCLib::Parameter(EyeLine,P[0]);
546     prof = Min (prof, ElCLib::Parameter(EyeLine,P[1]));
547     prof = Min (prof, ElCLib::Parameter(EyeLine,P[2]));
548   }
549
550   return prof;
551 }
552
553 //=======================================================================
554 //function : DetectedTriangle
555 //purpose  :
556 //=======================================================================
557 Standard_Boolean Select3D_SensitiveTriangulation::DetectedTriangle(gp_Pnt& P1,
558                                                                    gp_Pnt& P2,
559                                                                    gp_Pnt& P3) const
560 {
561   if(myDetectedTr==-1) return Standard_False; // currently not implemented...
562   const Poly_Array1OfTriangle& triangles = myTriangul->Triangles();
563   const TColgp_Array1OfPnt& Nodes = myTriangul->Nodes();
564   Standard_Integer n1,n2,n3;
565   triangles(myDetectedTr).Get(n1,n2,n3);
566
567   P1 = Nodes(n1);
568   P2 = Nodes(n2);
569   P3 = Nodes(n3);
570   if(myTrsf.Form()!=gp_Identity){
571     P1.Transform(myTrsf);
572     P2.Transform(myTrsf);
573     P3.Transform(myTrsf);
574   }
575
576   return Standard_True;
577 }
578
579 //=============================================================================
580 // Function : DetectedTriangle2d
581 // Purpose  :
582 //=============================================================================
583 Standard_Boolean Select3D_SensitiveTriangulation::DetectedTriangle2d(
584   gp_Pnt2d& P1, gp_Pnt2d& P2, gp_Pnt2d& P3) const
585 {
586   if(myDetectedTr==-1) 
587     return Standard_False; //  currently not implemented...
588   const Poly_Array1OfTriangle& triangles = myTriangul->Triangles();
589   const TColgp_Array1OfPnt& Nodes = myTriangul->Nodes();
590   Standard_Integer n1,n2,n3;
591   triangles( myDetectedTr ).Get(n1,n2,n3);
592
593   int aLower = myNodes2d.Lower();
594   int anUpper = myNodes2d.Upper();
595   if ( n1 >= aLower && n1 <= anUpper &&
596        n2 >= aLower && n2 <= anUpper &&
597        n3 >= aLower && n3 <= anUpper )
598   {
599     P1 = myNodes2d.Value( n1 );
600     P2 = myNodes2d.Value( n2 );
601     P3 = myNodes2d.Value( n3 );
602     return Standard_True;
603   }
604   else
605     return Standard_False;
606
607 }
608
609 void Select3D_SensitiveTriangulation::ComputeTotalTrsf()
610 {
611   Standard_Boolean hasloc = (HasLocation() || !myiniloc.IsIdentity());
612
613   if(hasloc){
614     if(myiniloc.IsIdentity())
615       myTrsf = Location().Transformation();
616     else if(HasLocation()){
617       myTrsf = (Location()*myiniloc).Transformation();
618     }
619     else
620       myTrsf = myiniloc.Transformation();
621   }
622   else{
623     gp_Trsf TheId;
624     myTrsf = TheId;
625   }
626 }