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