0023012: Detection gives incorrect results
[occt.git] / src / StdSelect / StdSelect_ViewerSelector3d.cxx
1 // Created on: 1995-03-15
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1995-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
22 #include <StdSelect_ViewerSelector3d.ixx>
23 #include <StdSelect.hxx>
24 #include <SelectBasics_SensitiveEntity.hxx>
25 #include <Graphic3d_AspectLine3d.hxx>
26 #include <gp_Pnt.hxx>
27 #include <gp_Lin.hxx>
28 #include <gp_Pnt2d.hxx>
29 #include <gp_Dir.hxx>
30 #include <gp_Ax3.hxx>
31 #include <gp_GTrsf.hxx>
32 #include <V3d_PerspectiveView.hxx>
33 #include <V3d_Plane.hxx>
34 #include <Select3D_SensitiveEntity.hxx>
35 #include <Graphic3d_Array1OfVertex.hxx>
36 #include <SelectMgr_DataMapIteratorOfDataMapOfIntegerSensitive.hxx>
37 #include <SelectBasics_ListOfBox2d.hxx>
38 #include <Visual3d_TransientManager.hxx>
39 #include <TColgp_HArray1OfPnt.hxx>
40 #include <TColgp_Array1OfPnt.hxx>
41 #include <TColgp_HArray1OfPnt2d.hxx>
42 #include <Select3D_SensitiveCurve.hxx>
43 #include <Select3D_SensitiveSegment.hxx>
44 #include <Select3D_SensitiveFace.hxx>
45 #include <Select3D_SensitiveCircle.hxx>
46 #include <Select3D_SensitivePoint.hxx>
47 #include <Select3D_SensitiveTriangulation.hxx>
48 #include <Select3D_SensitiveTriangle.hxx>
49 #include <Select3D_SensitiveWire.hxx>
50 #include <Select3D_SensitiveEntitySequence.hxx>
51 #include <Select3D_ListOfSensitiveTriangle.hxx>
52 #include <Select3D_SensitiveBox.hxx>
53 #include <Select3D_ListIteratorOfListOfSensitiveTriangle.hxx>
54
55 #include <SelectMgr_DataMapIteratorOfDataMapOfSelectionActivation.hxx>
56 #include <Aspect_TypeOfMarker.hxx>
57 #include <Graphic3d_AspectMarker3d.hxx>
58 #include <SelectBasics_ListIteratorOfListOfBox2d.hxx>
59 #include <Poly_Connect.hxx>
60 #include <TColStd_HArray1OfInteger.hxx>
61
62 #include <Poly_Array1OfTriangle.hxx>
63 #include <Poly_Triangulation.hxx>
64 #include <OSD_Environment.hxx>
65 #include <V3d.hxx>
66 #include <V3d_View.hxx>
67
68 static Standard_Integer StdSel_NumberOfFreeEdges (const Handle(Poly_Triangulation)& Trg)
69 {
70   Standard_Integer nFree = 0;
71   Poly_Connect pc(Trg);
72   Standard_Integer t[3];
73   Standard_Integer i, j;
74   for (i = 1; i <= Trg->NbTriangles(); i++)
75   {
76     pc.Triangles (i, t[0], t[1], t[2]);
77     for (j = 0; j < 3; j++)
78       if (t[j] == 0) nFree++;
79   }
80   return nFree;
81 }
82
83 static Standard_Boolean ReadIsDebugMode()
84 {
85   OSD_Environment StdSelectdb ("SELDEBUGMODE");
86   return !StdSelectdb.Value().IsEmpty();
87 }
88
89 static Standard_Boolean StdSelectDebugModeOn()
90 {
91   static const Standard_Boolean isDebugMode = ReadIsDebugMode();
92   return isDebugMode;
93 }
94
95 //==================================================
96 // Function:
97 // Purpose :
98 //==================================================
99
100 StdSelect_ViewerSelector3d
101 ::StdSelect_ViewerSelector3d():
102 myprj(new Select3D_Projector()),
103 mylastzoom(0.0),
104 mysensmode(StdSelect_SM_WINDOW),
105 mypixtol(2),
106 myupdatetol(Standard_True)
107 {
108   for (Standard_Integer i=0;i<=13;i++) {mycoeff [i] = 0.;myprevcoeff[i]=0.0;}
109   for (Standard_Integer j=0;j<2;j++) {mycenter [j] = 0.;myprevcenter[j]=0.0;}
110 }
111
112
113 //==================================================
114 // Function:
115 // Purpose :
116 //==================================================
117
118 StdSelect_ViewerSelector3d
119 ::StdSelect_ViewerSelector3d(const Handle(Select3D_Projector)& aProj):
120 myprj(aProj),
121 mylastzoom(0.0),
122 mysensmode(StdSelect_SM_WINDOW),
123 mypixtol(2),
124 myupdatetol(Standard_True)
125 {
126   for (Standard_Integer i=0;i<=13;i++) {mycoeff [i] = 0.;myprevcoeff[i]=0.0;}
127   for (Standard_Integer j=0;j<2;j++) {mycenter [j] = 0.;myprevcenter[j]=0.0;}
128 }
129
130 //==================================================
131 // Function: Convert
132 // Purpose :
133 //==================================================
134
135 void StdSelect_ViewerSelector3d::Convert(const Handle(SelectMgr_Selection)& aSel)
136 {
137   for(aSel->Init();aSel->More();aSel->Next())
138   {
139     if(aSel->Sensitive()->NeedsConversion())
140     {
141       Handle(Select3D_SensitiveEntity) SE = *((Handle(Select3D_SensitiveEntity)*) &(aSel->Sensitive()));
142       SE->Project(myprj);
143       if(!tosort) tosort=Standard_True;
144     }
145   }
146 }
147
148 //==================================================
149 // Function: Set
150 // Purpose :
151 //==================================================
152
153 void StdSelect_ViewerSelector3d
154 ::Set(const Handle(Select3D_Projector)& aProj)
155 {
156   myprj = aProj;
157   toupdate=Standard_True;
158 }
159
160 //==================================================
161 // Function: SetSensitivityMode
162 // Purpose :
163 //==================================================
164
165 void StdSelect_ViewerSelector3d
166 ::SetSensitivityMode(const StdSelect_SensitivityMode aMode)
167 {
168   mysensmode = aMode;
169   toupdate = Standard_True;
170 }
171
172 //==================================================
173 // Function: SetPixelTolerance
174 // Purpose :
175 //==================================================
176
177 void StdSelect_ViewerSelector3d
178 ::SetPixelTolerance(const Standard_Integer aTolerance)
179 {
180   if(mypixtol!=aTolerance)
181   {
182     mypixtol    = aTolerance;
183     myupdatetol = Standard_True;
184   }
185 }
186
187 //==================================================
188 // Function: SelectPix
189 // Purpose :
190 //==================================================
191
192 void StdSelect_ViewerSelector3d
193 ::Pick(const Standard_Integer XPix,
194        const Standard_Integer YPix,
195        const Handle(V3d_View)& aView)
196 {
197   UpdateProj(aView);
198   Standard_Real Xr3d,Yr3d,Zr3d;
199   gp_Pnt2d P2d;
200   aView->Convert(XPix,YPix,Xr3d,Yr3d,Zr3d);
201   myprj->Project(gp_Pnt(Xr3d,Yr3d,Zr3d),P2d);
202
203   // compute depth limits if clipping plane(s) enabled
204   gp_Lin anEyeLine = myprj->Shoot (P2d.X(), P2d.Y());
205   Standard_Real aPlaneA, aPlaneB, aPlaneC, aPlaneD;
206   Standard_Real aDepthFrom = ShortRealFirst();
207   Standard_Real aDepthTo   = ShortRealLast();
208   for (aView->InitActivePlanes(); aView->MoreActivePlanes(); aView->NextActivePlanes())
209   {
210     aView->ActivePlane()->Plane (aPlaneA, aPlaneB, aPlaneC, aPlaneD);
211     const gp_Dir& anEyeLineDir  = anEyeLine.Direction();
212     gp_Dir aPlaneNormal (aPlaneA, aPlaneB, aPlaneC);
213
214     Standard_Real aDotProduct = anEyeLineDir.Dot (aPlaneNormal);
215     Standard_Real aDirection = -(aPlaneD + anEyeLine.Location().XYZ().Dot (aPlaneNormal.XYZ()));
216     if (Abs (aDotProduct) < Precision::Angular())
217     {
218       // eyeline parallel to the clipping plane
219       if (aDirection > 0.0)
220       {
221         // invalidate the interval
222         aDepthTo   = ShortRealFirst();
223         aDepthFrom = ShortRealFirst();
224         break;
225       }
226       // just ignore this plane
227       continue;
228     }
229
230     // compute distance along the eyeline from eyeline location to intersection with clipping plane
231     Standard_Real aDepth = aDirection / aDotProduct;
232
233     // reduce depth limits
234     if (aDotProduct < 0.0)
235     {
236       if (aDepth < aDepthTo)
237       {
238         aDepthTo = aDepth;
239       }
240     }
241     else if (aDepth > aDepthFrom)
242     {
243       aDepthFrom = aDepth;
244     }
245   }
246   myprj->DepthMinMax (aDepthFrom, aDepthTo);
247
248   InitSelect(P2d.X(),P2d.Y());
249 }
250
251
252 //==================================================
253 // Function: InitSelect
254 // Purpose :
255 //==================================================
256
257 void StdSelect_ViewerSelector3d
258 ::Pick(const Standard_Integer XPMin,
259        const Standard_Integer YPMin,
260        const Standard_Integer XPMax,
261        const Standard_Integer YPMax,
262        const Handle(V3d_View)& aView)
263 {
264   if (myupdatetol && SensitivityMode() == StdSelect_SM_WINDOW)
265   {
266     SetSensitivity (aView->Convert (mypixtol));
267     myupdatetol = Standard_False;
268   }
269   UpdateProj (aView);
270
271   Standard_Real x1,y1,z1,x2,y2,z2;
272   gp_Pnt2d P2d_1,P2d_2;
273   aView->Convert(XPMin,YPMin,x1,y1,z1);
274   aView->Convert(XPMax,YPMax,x2,y2,z2);
275   myprj->Project(gp_Pnt(x1,y1,z1),P2d_1);
276   myprj->Project(gp_Pnt(x2,y2,z2),P2d_2);
277
278   InitSelect (Min(P2d_1.X(),P2d_2.X()),
279               Min(P2d_1.Y(),P2d_2.Y()),
280               Max(P2d_1.X(),P2d_2.X()),
281               Max(P2d_1.Y(),P2d_2.Y()));
282 }
283
284 //==================================================
285 // Function: Pick
286 // Purpose : Selection using a polyline
287 //==================================================
288
289 void StdSelect_ViewerSelector3d
290 ::Pick(const TColgp_Array1OfPnt2d& aPolyline,
291        const Handle(V3d_View)& aView)
292 {
293   if (myupdatetol && SensitivityMode() == StdSelect_SM_WINDOW)
294   {
295     SetSensitivity (aView->Convert (mypixtol));
296     myupdatetol = Standard_False;
297   }
298
299   UpdateProj (aView);
300
301   Standard_Integer NbPix = aPolyline.Length();
302   Standard_Integer i;
303
304   // Convert pixel
305   Handle(TColgp_HArray1OfPnt2d) P2d =
306     new TColgp_HArray1OfPnt2d(1,NbPix);
307
308   for (i = 1; i <= NbPix; ++i)
309   {
310     Standard_Real x,y,z;
311     Standard_Integer XP = (Standard_Integer)(aPolyline(i).X());
312     Standard_Integer YP = (Standard_Integer)(aPolyline(i).Y());
313     gp_Pnt2d Pnt2d;
314
315     aView->Convert (XP, YP, x, y, z);
316     myprj->Project (gp_Pnt (x, y, z), Pnt2d);
317
318     P2d->SetValue (i, Pnt2d);
319   }
320
321   const TColgp_Array1OfPnt2d& aPolyConvert = P2d->Array1();
322
323   InitSelect(aPolyConvert);
324 }
325
326 //==================================================
327 // Function: DisplayAreas
328 // Purpose : display the activated areas...
329 //==================================================
330
331 void StdSelect_ViewerSelector3d::
332 DisplayAreas(const Handle(V3d_View)& aView)
333 {
334   if (myupdatetol && SensitivityMode() == StdSelect_SM_WINDOW)
335   {
336     SetSensitivity (aView->Convert (mypixtol));
337                 myupdatetol = Standard_False;
338   }
339   UpdateProj(aView);
340   UpdateSort(); // Updates the activated areas
341
342   if(mystruct.IsNull())
343   {
344     mystruct = new Graphic3d_Structure(aView->Viewer()->Viewer());
345   }
346   if(myareagroup.IsNull())
347   {
348     myareagroup  = new Graphic3d_Group(mystruct);
349   }
350
351   SelectMgr_DataMapIteratorOfDataMapOfIntegerSensitive It(myentities);
352   Handle(Select3D_Projector) prj = StdSelect::GetProjector(aView);
353   prj->SetView(aView);
354
355
356   Graphic3d_Array1OfVertex Av1 (1,5);
357
358   Standard_Real xmin,ymin,xmax,ymax;
359   gp_Pnt Pbid;
360   SelectBasics_ListOfBox2d BoxList;
361
362   myareagroup->BeginPrimitives();
363   for (; It.More(); It.Next())
364   {
365     It.Value()->Areas(BoxList);
366     for (SelectBasics_ListIteratorOfListOfBox2d itb (BoxList); itb.More(); itb.Next())
367     {
368       itb.Value().Get (xmin, ymin, xmax, ymax);
369
370       Pbid.SetCoord (xmin - mytolerance, ymin - mytolerance, 0.0);
371       prj->Transform (Pbid, prj->InvertedTransformation());
372       Av1.SetValue (1, Graphic3d_Vertex (Pbid.X(), Pbid.Y(), Pbid.Z()));
373
374       Pbid.SetCoord (xmax + mytolerance, ymin - mytolerance, 0.0);
375       prj->Transform (Pbid, prj->InvertedTransformation());
376       Av1.SetValue (2, Graphic3d_Vertex (Pbid.X(), Pbid.Y(), Pbid.Z()));
377
378       Pbid.SetCoord (xmax + mytolerance, ymax + mytolerance, 0.0);
379       prj->Transform (Pbid, prj->InvertedTransformation());
380       Av1.SetValue (3, Graphic3d_Vertex (Pbid.X(), Pbid.Y(), Pbid.Z()));
381
382       Pbid.SetCoord (xmin - mytolerance, ymax + mytolerance, 0.0);
383       prj->Transform (Pbid, prj->InvertedTransformation());
384       Av1.SetValue (4,Graphic3d_Vertex (Pbid.X(), Pbid.Y(), Pbid.Z()));
385
386       Pbid.SetCoord (xmin - mytolerance, ymin - mytolerance, 0.0);
387       prj->Transform (Pbid, prj->InvertedTransformation());
388       Av1.SetValue (5, Graphic3d_Vertex (Pbid.X(), Pbid.Y(), Pbid.Z()));
389
390       myareagroup->Polyline (Av1);
391     }
392   }
393
394   myareagroup->EndPrimitives();
395   myareagroup->SetGroupPrimitivesAspect (new
396     Graphic3d_AspectLine3d (Quantity_NOC_AQUAMARINE1, Aspect_TOL_DASH, 1.0));
397   myareagroup->Structure()->SetDisplayPriority(10);
398   myareagroup->Structure()->Display();
399
400   if(aView->TransientManagerBeginDraw())
401   {
402     Visual3d_TransientManager::DrawStructure(mystruct);
403     Visual3d_TransientManager::EndDraw();
404   }
405   else
406   {
407     aView->Update();
408   }
409 }
410
411 //==================================================
412 // Function: ClearAreas
413 // Purpose :
414 //==================================================
415
416 void StdSelect_ViewerSelector3d::
417 ClearAreas(const Handle(V3d_View)& aView)
418 {
419   if(myareagroup.IsNull()) return;
420   myareagroup->Clear();
421   if(aView.IsNull()) return;
422   if(aView->TransientManagerBeginDraw())
423     Visual3d_TransientManager::EndDraw();
424   else
425     aView->Update();
426 }
427
428 //==================================================
429 // Function: updateproj
430 // Purpose : at any time verifies that
431 //           the view coefficients did not change :
432 // store current view coeffts
433 //        in static array cf [ 0->2 At coordinates XAT YAT ZAT
434 //                            3->5 Up coordinates XUP YUP ZUP
435 //                            6->8 ProjVect coordinates DX DY DZ
436 //                             9   focale
437 //                            10   1. if pers 0. else
438 //==================================================
439
440 Standard_Boolean  StdSelect_ViewerSelector3d::
441 UpdateProj(const Handle(V3d_View)& aView)
442 {
443   myprevcoeff[ 9] = 0.0;
444   myprevcoeff[10] = 0.0;
445   Standard_Boolean Pers = Standard_False;
446   if (aView->Type() == V3d_PERSPECTIVE)
447   {
448     Pers = Standard_True;
449     myprevcoeff[10] = 1.0;
450     myprevcoeff[ 9] = aView->Focale();
451   }
452   aView->At (myprevcoeff[0], myprevcoeff[1], myprevcoeff[2]);
453   aView->Up (myprevcoeff[3], myprevcoeff[4], myprevcoeff[5]);
454   aView->Proj (myprevcoeff[6], myprevcoeff[7], myprevcoeff[8]);
455   aView->AxialScale (myprevcoeff[11], myprevcoeff[12], myprevcoeff[13]);
456   aView->Center (myprevcenter[0], myprevcenter[1]);
457   Standard_Integer ii;
458
459   for (ii = 0; ii <= 13 && (myprevcoeff[ii] == mycoeff[ii]); ++ii) {}
460   if (ii <= 13 || (myprevcenter[0] != mycenter[0]) || (myprevcenter[1] != mycenter[1]))
461   {
462     if (StdSelectDebugModeOn())
463     {
464       cout<<"\t\t\t\t\t VS3d::UpdateProj====> coefficients changes on reprojette"<<endl;
465       cout<<"\t\t\t\t\t";
466       for (Standard_Integer i = 1; i <= 9; ++i)
467       {
468         cout<<mycoeff[i-1]<<"  ";
469         if (i%3==0)
470           cout<<"\n\t\t\t\t\t";
471       }
472       cout<<"focale :"<<mycoeff[9]<<" persp :"<<mycoeff[10]<<endl;
473       cout<<"center :"<<mycenter[0]<<"  "<<mycenter[1]<<endl;
474     }
475     toupdate = Standard_True;
476     myupdatetol = Standard_True;
477     for (Standard_Integer imod = ii; imod <= 13; ++imod)
478     {
479       mycoeff[imod] = myprevcoeff[imod];
480     }
481     for (Standard_Integer jmod = 0; jmod < 2; ++jmod)
482     {
483       mycenter[jmod] = myprevcenter[jmod];
484     }
485
486     gp_Dir Zpers (mycoeff[6], mycoeff[7], mycoeff[8]);
487     gp_Dir Ypers (mycoeff[3], mycoeff[4], mycoeff[5]);
488     gp_Dir Xpers = Ypers.Crossed (Zpers);
489     gp_XYZ loc (mycoeff[0], mycoeff[1], mycoeff[2]);
490     gp_Mat matrix;
491     matrix.SetCols (Xpers.XYZ(), Ypers.XYZ(), Zpers.XYZ());
492     gp_Mat matScale (mycoeff[11], 0, 0, 0, mycoeff[12], 0, 0, 0, mycoeff[13]);
493     matrix.Transpose();
494     loc.Multiply (matrix);
495     loc.Reverse ();
496     matrix.Multiply (matScale);
497     gp_GTrsf GT;
498     GT.SetTranslationPart (loc);
499     GT.SetVectorialPart (matrix);
500
501     myprj = new Select3D_Projector (GT, Pers, mycoeff[9]);
502
503     // SAV 08/05/02 : fix for detection problem in a perspective view
504     if (aView->Type() == V3d_PERSPECTIVE)
505       myprj->SetView (aView);
506     // NKV 31/07/07 : fix for detection problem in case of custom matrix
507     else if (aView->ViewOrientation().IsCustomMatrix())
508       myprj->SetView (aView);
509   }
510
511   if (Abs (aView->Scale() - mylastzoom) > 1.e-3)
512   {
513     myupdatetol = Standard_True;
514     mylastzoom = aView->Scale();
515   }
516
517   if (myupdatetol && SensitivityMode() == StdSelect_SM_WINDOW)
518   {
519     SetSensitivity (aView->Convert (mypixtol));
520     myupdatetol = Standard_False;
521   }
522
523   if (toupdate) UpdateConversion();
524   if (tosort) UpdateSort();
525
526   return Standard_True;
527 }
528
529
530 //=============================
531 // Function: DisplaySensitive.
532 // Purpose : Display active primitives.
533 //=============================
534 void StdSelect_ViewerSelector3d::DisplaySensitive(const Handle(V3d_View)& aViou)
535 {
536   if (myupdatetol && SensitivityMode() == StdSelect_SM_WINDOW)
537   {
538     SetSensitivity (aViou->Convert (mypixtol));
539                 myupdatetol = Standard_False;
540   }
541   if(toupdate) UpdateProj(aViou);
542   if(tosort) UpdateSort(); // Updates the activated areas
543
544   // Preparation des structures
545   if(mystruct.IsNull())
546     mystruct = new Graphic3d_Structure(aViou->Viewer()->Viewer());
547
548   if(mysensgroup.IsNull())
549     mysensgroup = new Graphic3d_Group(mystruct);
550
551   Quantity_Color Col(Quantity_NOC_INDIANRED3);
552   Handle(Graphic3d_AspectMarker3d) AM =
553     new Graphic3d_AspectMarker3d(Aspect_TOM_O_PLUS,Col,2.);
554   mysensgroup-> SetPrimitivesAspect (AM);
555   mysensgroup->SetPrimitivesAspect (
556     new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
557
558   // Remplissage de la structure...
559
560   SelectMgr_DataMapIteratorOfDataMapOfSelectionActivation It(myselections);
561   // Standard_Integer isel (0);
562
563   mysensgroup->BeginPrimitives();
564   for (; It.More(); It.Next())
565   {
566     if (It.Value()==0)
567     {
568       const Handle(SelectMgr_Selection)& Sel = It.Key();
569       ComputeSensitivePrs(Sel);
570     }
571   }
572   mysensgroup->EndPrimitives();
573
574   mysensgroup->Structure()->SetDisplayPriority(10);
575   mystruct->Display();
576   if (aViou->TransientManagerBeginDraw())
577   {
578     Visual3d_TransientManager::DrawStructure(mystruct);
579     Visual3d_TransientManager::EndDraw();
580   }
581   else if (!aViou.IsNull())
582   {
583     aViou->Update();
584   }
585 }
586
587 //=============================
588 // Function: ClearSensitive
589 // Purpose :
590 //=============================
591 void StdSelect_ViewerSelector3d::ClearSensitive(const Handle(V3d_View)& aViou)
592 {
593   if(mysensgroup.IsNull()) return;
594   mysensgroup->Clear();
595   if(aViou.IsNull()) return;
596
597   if(aViou->TransientManagerBeginDraw())
598     Visual3d_TransientManager::EndDraw();
599   else
600     aViou->Update();
601 }
602
603 //=======================================================================
604 //function : DisplaySenstive
605 //purpose  :
606 //=======================================================================
607 void StdSelect_ViewerSelector3d::
608 DisplaySensitive (const Handle(SelectMgr_Selection)& Sel,
609                   const Handle(V3d_View)& aViou,
610                   const Standard_Boolean ClearOthers)
611 {
612   if (mystruct.IsNull())
613     mystruct = new Graphic3d_Structure (aViou->Viewer()->Viewer());
614   if (mysensgroup.IsNull())
615   {
616     mysensgroup = new Graphic3d_Group (mystruct);
617     Quantity_Color Col (Quantity_NOC_INDIANRED3);
618     Handle(Graphic3d_AspectMarker3d) AM =
619       new Graphic3d_AspectMarker3d (Aspect_TOM_O_PLUS, Col, 2.0);
620     mysensgroup-> SetPrimitivesAspect (AM);
621     mysensgroup->SetPrimitivesAspect (
622       new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
623   }
624
625   if(ClearOthers) mysensgroup->Clear();
626
627   mysensgroup->BeginPrimitives();
628
629   ComputeSensitivePrs(Sel);
630
631   mysensgroup->EndPrimitives();
632   mystruct->SetDisplayPriority(10);
633   mystruct->Display();
634   if(aViou->TransientManagerBeginDraw())
635   {
636     Visual3d_TransientManager::DrawStructure(mystruct);
637     Visual3d_TransientManager::EndDraw();
638   }
639   else if(!aViou.IsNull())
640   {
641     aViou->Update();
642   }
643 }
644
645 //=======================================================================
646 //function : DisplayAreas
647 //purpose  :
648 //=======================================================================
649
650 void StdSelect_ViewerSelector3d::
651 DisplayAreas (const Handle(SelectMgr_Selection)& Sel,
652               const Handle(V3d_View)& aViou,
653               const Standard_Boolean ClearOthers)
654 {
655   if (mystruct.IsNull())
656     mystruct = new Graphic3d_Structure (aViou->Viewer()->Viewer());
657   if (mysensgroup.IsNull())
658   {
659     myareagroup = new Graphic3d_Group (mystruct);
660     myareagroup->SetGroupPrimitivesAspect (
661       new Graphic3d_AspectLine3d (Quantity_NOC_AQUAMARINE1, Aspect_TOL_DASH, 1.0));
662   }
663
664   if(ClearOthers) myareagroup->Clear();
665
666   myareagroup->BeginPrimitives();
667   ComputeAreasPrs(Sel);
668   myareagroup->EndPrimitives();
669
670   mystruct->SetDisplayPriority(10);
671   mystruct->Display();
672
673   if(aViou->TransientManagerBeginDraw())
674   {
675     Visual3d_TransientManager::DrawStructure(mystruct);
676     Visual3d_TransientManager::EndDraw();
677   }
678   else
679   {
680     aViou->Update();
681   }
682 }
683
684 //=======================================================================
685 //function : ComputeSensitivePrs
686 //purpose  :
687 //=======================================================================
688
689 void StdSelect_ViewerSelector3d::
690 ComputeSensitivePrs(const Handle(SelectMgr_Selection)& Sel)
691 {
692   for(Sel->Init();Sel->More();Sel->Next())
693   {
694     Handle(Select3D_SensitiveEntity) Ent =
695       Handle(Select3D_SensitiveEntity)::DownCast(Sel->Sensitive());
696     Standard_Boolean hasloc = (Ent.IsNull()) ? Standard_False:
697       (Ent->HasLocation()? Standard_True:Standard_False);
698
699     TopLoc_Location theloc;
700     if(hasloc)
701       theloc = Ent->Location();
702
703     //==============
704     // Box
705     //=============
706
707     if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveBox))
708     {
709       const Bnd_Box& B = Handle(Select3D_SensitiveBox)::DownCast (Ent)->Box();
710       Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
711       B.Get (xmin, ymin, zmin, xmax, ymax, zmax);
712       gp_Pnt theboxpoint[8] =
713       {
714         gp_Pnt(xmin,ymin,zmin),
715         gp_Pnt(xmax,ymin,zmin),
716         gp_Pnt(xmax,ymax,zmin),
717         gp_Pnt(xmin,ymax,zmin),
718         gp_Pnt(xmin,ymin,zmax),
719         gp_Pnt(xmax,ymin,zmax),
720         gp_Pnt(xmax,ymax,zmax),
721         gp_Pnt(xmin,ymax,zmax)
722       };
723       if(hasloc)
724       {
725         for (Standard_Integer ii = 0; ii <= 7; ii++)
726           theboxpoint[ii].Transform (theloc.Transformation());
727       }
728       Graphic3d_Array1OfVertex Vtx (1, 5);
729
730       Standard_Integer ip;
731       for (ip = 0; ip < 4; ip++)
732       {
733         Vtx.SetValue (ip + 1, Graphic3d_Vertex (theboxpoint[ip].X(),
734                                                 theboxpoint[ip].Y(),
735                                                 theboxpoint[ip].Z()));
736       }
737       mysensgroup->Polyline (Vtx);
738       for (ip = 0; ip < 4; ip++)
739       {
740         Vtx.SetValue (ip + 1, Graphic3d_Vertex (theboxpoint[ip + 4].X(),
741                                                 theboxpoint[ip + 4].Y(),
742                                                 theboxpoint[ip + 4].Z()));
743       }
744       mysensgroup->Polyline (Vtx);
745
746       Graphic3d_Array1OfVertex Vtx2 (1, 2);
747       for (ip = 0; ip < 4; ip++)
748       {
749         Vtx2.SetValue (1, Graphic3d_Vertex (theboxpoint[ip].X(),
750                                             theboxpoint[ip].Y(),
751                                             theboxpoint[ip].Z()));
752
753         Vtx2.SetValue (2, Graphic3d_Vertex (theboxpoint[ip + 4].X(),
754                                             theboxpoint[ip + 4].Y(),
755                                             theboxpoint[ip + 4].Z()));
756         mysensgroup->Polyline (Vtx2);
757       }
758     }
759     //==============
760     // Face
761     //=============
762     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveFace))
763     {
764       Handle(Select3D_SensitiveFace) aFace = Handle(Select3D_SensitiveFace)::DownCast(Ent);
765       Handle(TColgp_HArray1OfPnt) TheHPts;
766       aFace->Points3D(TheHPts);
767       const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
768
769       Graphic3d_Array1OfVertex Vtx (ThePts.Lower(), ThePts.Upper());
770
771       for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
772       {
773         if (hasloc)
774         {
775           const gp_Pnt& curP = ThePts (I);
776           gp_Pnt ptrans = curP.Transformed (theloc.Transformation()).XYZ();
777           Vtx.SetValue (I, Graphic3d_Vertex (ptrans.X(), ptrans.Y(), ptrans.Z()));
778         }
779         else
780         {
781           Vtx.SetValue (I, Graphic3d_Vertex (ThePts (I).X(), ThePts (I).Y(), ThePts (I).Z()));
782         }
783       }
784       mysensgroup->Polyline (Vtx);
785     }
786     //==============
787     // Curve
788     //=============
789     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCurve))
790     {
791       Handle(Select3D_SensitiveCurve) aCurve = Handle(Select3D_SensitiveCurve)::DownCast(Ent);
792       Handle(TColgp_HArray1OfPnt) TheHPts;
793       aCurve->Points3D(TheHPts);
794       const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
795
796       Graphic3d_Array1OfVertex Vtx (ThePts.Lower(), ThePts.Upper());
797       for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
798       {
799         if (hasloc)
800         {
801           gp_Pnt ptrans (ThePts (I).Transformed (theloc.Transformation()).XYZ());
802           Vtx.SetValue (I, Graphic3d_Vertex (ptrans.X(), ptrans.Y(), ptrans.Z()));
803         }
804         else
805         {
806           Vtx.SetValue (I, Graphic3d_Vertex (ThePts (I).X(), ThePts (I).Y(), ThePts (I).Z()));
807         }
808       }
809       mysensgroup->Polyline (Vtx);
810     }
811     //==============
812     // Wire
813     //=============
814     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveWire))
815     {
816         Handle(Select3D_SensitiveWire) aWire = Handle(Select3D_SensitiveWire)::DownCast(Ent);
817         Select3D_SensitiveEntitySequence EntitySeq;
818         aWire->GetEdges (EntitySeq);
819
820       for (int i = 1; i <= EntitySeq.Length(); i++)
821       {
822         Handle(Select3D_SensitiveEntity) SubEnt = Handle(Select3D_SensitiveEntity)::DownCast(EntitySeq.Value(i));
823
824         //Segment
825         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveSegment))
826         {
827           Graphic3d_Array1OfVertex Vtx (1, 2);
828           gp_Pnt P1 (Handle(Select3D_SensitiveSegment)::DownCast(SubEnt)->StartPoint().XYZ());
829           gp_Pnt P2 (Handle(Select3D_SensitiveSegment)::DownCast(SubEnt)->EndPoint().XYZ());
830           if (hasloc)
831           {
832             P1.Transform(theloc.Transformation());
833             P2.Transform(theloc.Transformation());
834           }
835           Vtx.SetValue (1, Graphic3d_Vertex (P1.X(), P1.Y(), P1.Z()));
836           Vtx.SetValue (2, Graphic3d_Vertex (P2.X(), P2.Y(), P2.Z()));
837           mysensgroup->Polyline (Vtx);
838         }
839
840         //circle
841         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCircle))
842         {
843           Handle(Select3D_SensitiveCircle) C = Handle(Select3D_SensitiveCircle)::DownCast(SubEnt);
844           Standard_Integer Lo, Up;
845           C->ArrayBounds (Lo, Up);
846           Standard_Integer II = Lo;
847           while (II <= Up - 2)
848           {
849             Graphic3d_Array1OfVertex Vtx (1, 4);
850             gp_Pnt ThePts[3] =
851             {
852               gp_Pnt (C->GetPoint3d (II).XYZ()),
853               gp_Pnt (C->GetPoint3d (++II).XYZ()),
854               gp_Pnt (C->GetPoint3d (++II).XYZ())
855             };
856
857             if (hasloc)
858             {
859               for (Standard_Integer jj = 0; jj <= 2; jj++)
860                 ThePts[jj].Transform (theloc.Transformation());
861             }
862
863             Vtx.SetValue (1, Graphic3d_Vertex (ThePts[0].X(), ThePts[0].Y(), ThePts[0].Z()));
864             Vtx.SetValue (2, Graphic3d_Vertex (ThePts[1].X(), ThePts[1].Y(), ThePts[1].Z()));
865             Vtx.SetValue (3, Graphic3d_Vertex (ThePts[2].X(), ThePts[2].Y(), ThePts[2].Z()));
866             Vtx.SetValue (4, Graphic3d_Vertex (ThePts[0].X(), ThePts[0].Y(), ThePts[0].Z()));
867
868             mysensgroup->Polyline (Vtx);
869           }
870         }
871
872         //curve
873         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCurve))
874         {
875           Handle(Select3D_SensitiveCurve) aCurve = Handle(Select3D_SensitiveCurve)::DownCast(SubEnt);
876           Handle(TColgp_HArray1OfPnt) TheHPts;
877           aCurve->Points3D (TheHPts);
878           const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
879           Graphic3d_Array1OfVertex Vtx (ThePts.Lower(), ThePts.Upper());
880           for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
881           {
882             if (hasloc)
883             {
884               gp_Pnt ptrans (ThePts (I).Transformed (theloc.Transformation()).XYZ());
885               Vtx.SetValue (I, Graphic3d_Vertex (ptrans.X(), ptrans.Y(), ptrans.Z()));
886             }
887             else
888             {
889               Vtx.SetValue (I, Graphic3d_Vertex (ThePts (I).X(), ThePts (I).Y(), ThePts (I).Z()));
890             }
891           }
892           mysensgroup->Polyline (Vtx);
893         }
894       }
895     }
896     //==============
897     // Segment
898     //=============
899     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveSegment))
900     {
901       Graphic3d_Array1OfVertex Vtx (1,2);
902       gp_Pnt P1 (Handle(Select3D_SensitiveSegment)::DownCast(Ent)->StartPoint().XYZ());
903       gp_Pnt P2 (Handle(Select3D_SensitiveSegment)::DownCast(Ent)->EndPoint().XYZ());
904       if (hasloc)
905       {
906         P1.Transform (theloc.Transformation());
907         P2.Transform (theloc.Transformation());
908       }
909       Vtx.SetValue (1, Graphic3d_Vertex (P1.X(), P1.Y(), P1.Z()));
910       Vtx.SetValue (2, Graphic3d_Vertex (P2.X(), P2.Y(), P2.Z()));
911       mysensgroup->Polyline (Vtx);
912     }
913     //==============
914     // Circle
915     //=============
916     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCircle))
917     {
918       Handle(Select3D_SensitiveCircle) C = Handle(Select3D_SensitiveCircle)::DownCast(Ent);
919       Standard_Integer Lo, Up;
920       C->ArrayBounds (Lo, Up);
921       Standard_Integer II = Lo;
922       while (II <= Up - 2)
923       {
924         Graphic3d_Array1OfVertex Vtx (1,4);
925         gp_Pnt ThePts[3] =
926         {
927           gp_Pnt (C->GetPoint3d (II).XYZ()),
928           gp_Pnt (C->GetPoint3d (++II).XYZ()),
929           gp_Pnt (C->GetPoint3d (++II).XYZ())
930         };
931
932         if (hasloc)
933         {
934           for (Standard_Integer jj = 0; jj <= 2; jj++)
935             ThePts[jj].Transform (theloc.Transformation());
936         }
937
938         Vtx.SetValue (1, Graphic3d_Vertex (ThePts[0].X(), ThePts[0].Y(), ThePts[0].Z()));
939         Vtx.SetValue (2, Graphic3d_Vertex (ThePts[1].X(), ThePts[1].Y(), ThePts[1].Z()));
940         Vtx.SetValue (3, Graphic3d_Vertex (ThePts[2].X(), ThePts[2].Y(), ThePts[2].Z()));
941         Vtx.SetValue (4, Graphic3d_Vertex (ThePts[0].X(), ThePts[0].Y(), ThePts[0].Z()));
942
943         mysensgroup->Polyline (Vtx);
944       }
945     }
946     //==============
947     // Point
948     //=============
949     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitivePoint))
950     {
951       gp_Pnt P = hasloc ?
952         Handle(Select3D_SensitivePoint)::DownCast(Ent)->Point() :
953         Handle(Select3D_SensitivePoint)::DownCast(Ent)->Point().Transformed (theloc.Transformation());
954       Graphic3d_Vertex V (P.X(), P.Y(), P.Z());
955       mysensgroup->Marker (V);
956     }
957     //============================================================
958     // Triangulation : On met un petit offset ves l'interieur...
959     //==========================================================
960     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveTriangulation))
961     {
962       const Handle(Poly_Triangulation)& PT =
963         (*((Handle(Select3D_SensitiveTriangulation)*) &Ent))->Triangulation();
964
965       const Poly_Array1OfTriangle& triangles = PT->Triangles();
966       const TColgp_Array1OfPnt& Nodes = PT->Nodes();
967       //      gp_Pnt P1, P2, P3;
968       Standard_Integer n[3];
969       Graphic3d_Array1OfVertex AV (1, 4);
970
971       TopLoc_Location iloc, bidloc;
972       if ((*((Handle(Select3D_SensitiveTriangulation)*) &Ent))->HasInitLocation())
973         bidloc = (*((Handle(Select3D_SensitiveTriangulation)*) &Ent))->GetInitLocation();
974
975       if (bidloc.IsIdentity())
976         iloc = theloc;
977       else
978         iloc = theloc * bidloc;
979
980       Standard_Integer i;
981       for (i = 1; i <= PT->NbTriangles(); i++)
982       {
983         triangles (i).Get (n[0], n[1], n[2]);
984         gp_Pnt P1 (Nodes (n[0]).Transformed (iloc));
985         gp_Pnt P2 (Nodes (n[1]).Transformed (iloc));
986         gp_Pnt P3 (Nodes (n[2]).Transformed (iloc));
987         gp_XYZ V1 (P1.XYZ());
988         gp_XYZ V2 (P2.XYZ());
989         gp_XYZ V3 (P3.XYZ());
990         gp_XYZ CDG (P1.XYZ()); CDG += (P2.XYZ()); CDG += (P3.XYZ()); CDG /= 3.0;
991
992         V1 -= CDG; V2 -= CDG; V3 -= CDG;
993
994         V1 *= 0.9; V2 *= 0.9; V3 *= 0.9;
995         V1 += CDG; V2 += CDG; V3 += CDG;
996         AV.SetValue (1, Graphic3d_Vertex (V1.X(), V1.Y(), V1.Z()));
997         AV.SetValue (2, Graphic3d_Vertex (V2.X(), V2.Y(), V2.Z()));
998         AV.SetValue (3, Graphic3d_Vertex (V3.X(), V3.Y(), V3.Z()));
999         AV.SetValue (4, Graphic3d_Vertex (V1.X(), V1.Y(), V1.Z()));
1000         mysensgroup->Polyline (AV);
1001       }
1002
1003       // recherche des bords libres...
1004
1005       Handle(TColStd_HArray1OfInteger) FreeEdges = new TColStd_HArray1OfInteger (1, 2 * StdSel_NumberOfFreeEdges (PT));
1006       TColStd_Array1OfInteger& FreeE = FreeEdges->ChangeArray1();
1007       Poly_Connect pc (PT);
1008       Standard_Integer t[3];
1009       Standard_Integer j;
1010       Standard_Integer fr (1);
1011       for (i = 1; i <= PT->NbTriangles(); i++)
1012       {
1013         pc.Triangles (i, t[0], t[1], t[2]);
1014         triangles (i).Get (n[0], n[1], n[2]);
1015         for (j = 0; j < 3; j++)
1016         {
1017           Standard_Integer k = (j + 1) % 3;
1018           if (t[j] == 0)
1019           {
1020             FreeE (fr)    = n[j];
1021             FreeE (fr + 1)= n[k];
1022             fr += 2;
1023           }
1024         }
1025       }
1026       Standard_Integer Node1, Node2;
1027       mysensgroup->SetPrimitivesAspect (
1028         new Graphic3d_AspectLine3d (Quantity_NOC_GREEN, Aspect_TOL_SOLID, 2.0));
1029       for (Standard_Integer ifri = 1; ifri <= FreeE.Length(); ifri += 2)
1030       {
1031         Node1 = FreeE (ifri);
1032         Node2 = FreeE (ifri + 1);
1033         Graphic3d_Array1OfVertex FE (1, 2);
1034         gp_Pnt pe1 (Nodes (Node1).Transformed (iloc)), pe2 (Nodes (Node2).Transformed (iloc));
1035         FE.SetValue (1,Graphic3d_Vertex (pe1.X(), pe1.Y(), pe1.Z()));
1036         FE.SetValue (2,Graphic3d_Vertex (pe2.X(), pe2.Y(), pe2.Z()));
1037         mysensgroup->Polyline (FE);
1038       }
1039
1040       mysensgroup->SetPrimitivesAspect (
1041         new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
1042     }
1043     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveTriangle))
1044     {
1045       Handle(Select3D_SensitiveTriangle) Str = Handle(Select3D_SensitiveTriangle)::DownCast(Ent);
1046       gp_Pnt P1, P2, P3, CDG;
1047       Graphic3d_Array1OfVertex AV (1, 4);
1048       Str->Points3D (P1, P2, P3);
1049       CDG = Str->Center3D();
1050
1051       gp_XYZ V1 (P1.XYZ()); V1 -= (CDG.XYZ());
1052       gp_XYZ V2 (P2.XYZ()); V2 -= (CDG.XYZ());
1053       gp_XYZ V3 (P3.XYZ()); V3 -= (CDG.XYZ());
1054
1055       V1 *= 0.9; V2 *= 0.9; V3 *= 0.9;
1056       V1 += CDG.XYZ(); V2 += CDG.XYZ(); V3 += CDG.XYZ();
1057       AV.SetValue (1, Graphic3d_Vertex (V1.X(), V1.Y(), V1.Z()));
1058       AV.SetValue (2, Graphic3d_Vertex (V2.X(), V2.Y(), V2.Z()));
1059       AV.SetValue (3, Graphic3d_Vertex (V3.X(), V3.Y(), V3.Z()));
1060       AV.SetValue (4, Graphic3d_Vertex (V1.X(), V1.Y(), V1.Z()));
1061       mysensgroup->Polyline (AV);
1062     }
1063   }
1064 }
1065
1066 //=======================================================================
1067 //function : ComputeAreaPrs
1068 //purpose  :
1069 //=======================================================================
1070
1071 void StdSelect_ViewerSelector3d::
1072 ComputeAreasPrs (const Handle(SelectMgr_Selection)& Sel)
1073 {
1074   // Select3D_Projector myprj = StdSelect::GetProjector (aView);
1075   Graphic3d_Array1OfVertex Av1 (1, 5);
1076   Standard_Real xmin, ymin, xmax, ymax;
1077   gp_Pnt Pbid;
1078   SelectBasics_ListOfBox2d BoxList;
1079
1080   for (Sel->Init(); Sel->More(); Sel->Next())
1081   {
1082     Sel->Sensitive()->Areas (BoxList);
1083     for (SelectBasics_ListIteratorOfListOfBox2d itb (BoxList); itb.More(); itb.Next())
1084     {
1085       itb.Value().Get (xmin, ymin, xmax, ymax);
1086
1087       Pbid.SetCoord (xmin - mytolerance, ymin - mytolerance, 0.0);
1088       myprj->Transform (Pbid, myprj->InvertedTransformation());
1089       Av1.SetValue (1, Graphic3d_Vertex (Pbid.X(), Pbid.Y(), Pbid.Z()));
1090
1091       Pbid.SetCoord (xmax + mytolerance, ymin - mytolerance, 0.0);
1092       myprj->Transform (Pbid, myprj->InvertedTransformation());
1093       Av1.SetValue (2, Graphic3d_Vertex (Pbid.X(), Pbid.Y(), Pbid.Z()));
1094
1095       Pbid.SetCoord (xmax + mytolerance, ymax + mytolerance, 0.0);
1096       myprj->Transform (Pbid, myprj->InvertedTransformation());
1097       Av1.SetValue (3, Graphic3d_Vertex (Pbid.X(), Pbid.Y(), Pbid.Z()));
1098
1099       Pbid.SetCoord (xmin - mytolerance, ymax + mytolerance, 0.0);
1100       myprj->Transform (Pbid, myprj->InvertedTransformation());
1101       Av1.SetValue (4, Graphic3d_Vertex (Pbid.X(), Pbid.Y(), Pbid.Z()));
1102
1103       Pbid.SetCoord (xmin - mytolerance, ymin - mytolerance, 0.0);
1104       myprj->Transform (Pbid, myprj->InvertedTransformation());
1105       Av1.SetValue (5, Graphic3d_Vertex (Pbid.X(), Pbid.Y(), Pbid.Z()));
1106
1107       myareagroup->Polyline (Av1);
1108     }
1109   }
1110 }
1111
1112 //=======================================================================
1113 //function : ReactivateProjector
1114 //purpose  :
1115 //=======================================================================
1116 void StdSelect_ViewerSelector3d::ReactivateProjector()
1117 {
1118   Handle(SelectBasics_SensitiveEntity) BS;
1119   for (SelectMgr_DataMapIteratorOfDataMapOfIntegerSensitive it (myentities); it.More(); it.Next())
1120   {
1121     BS = it.Value();
1122     if (BS->Is3D())
1123     {
1124       (*((Handle(Select3D_SensitiveEntity)*) &BS))->SetLastPrj (myprj);
1125     }
1126   }
1127 }