87885ce2c57db5f500fe6a920c868f6db5eb99eb
[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_ArrayOfPolylines.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 <Graphic3d_ArrayOfPoints.hxx>
59 #include <SelectBasics_ListIteratorOfListOfBox2d.hxx>
60 #include <Poly_Connect.hxx>
61 #include <TColStd_HArray1OfInteger.hxx>
62
63 #include <Poly_Array1OfTriangle.hxx>
64 #include <Poly_Triangulation.hxx>
65 #include <OSD_Environment.hxx>
66 #include <V3d.hxx>
67 #include <V3d_View.hxx>
68 #include <TColgp_SequenceOfPnt.hxx>
69
70
71 static Standard_Integer StdSel_NumberOfFreeEdges (const Handle(Poly_Triangulation)& Trg)
72 {
73   Standard_Integer nFree = 0;
74   Poly_Connect pc(Trg);
75   Standard_Integer t[3];
76   Standard_Integer i, j;
77   for (i = 1; i <= Trg->NbTriangles(); i++)
78   {
79     pc.Triangles (i, t[0], t[1], t[2]);
80     for (j = 0; j < 3; j++)
81       if (t[j] == 0) nFree++;
82   }
83   return nFree;
84 }
85
86 static Standard_Boolean ReadIsDebugMode()
87 {
88   OSD_Environment StdSelectdb ("SELDEBUGMODE");
89   return !StdSelectdb.Value().IsEmpty();
90 }
91
92 static Standard_Boolean StdSelectDebugModeOn()
93 {
94   static const Standard_Boolean isDebugMode = ReadIsDebugMode();
95   return isDebugMode;
96 }
97
98 //==================================================
99 // Function:
100 // Purpose :
101 //==================================================
102
103 StdSelect_ViewerSelector3d
104 ::StdSelect_ViewerSelector3d():
105 myprj(new Select3D_Projector()),
106 mylastzoom(0.0),
107 mysensmode(StdSelect_SM_WINDOW),
108 mypixtol(2),
109 myupdatetol(Standard_True)
110 {
111   for (Standard_Integer i=0;i<=13;i++) {mycoeff [i] = 0.;myprevcoeff[i]=0.0;}
112   for (Standard_Integer j=0;j<2;j++) {mycenter [j] = 0.;myprevcenter[j]=0.0;}
113 }
114
115
116 //==================================================
117 // Function:
118 // Purpose :
119 //==================================================
120
121 StdSelect_ViewerSelector3d
122 ::StdSelect_ViewerSelector3d(const Handle(Select3D_Projector)& aProj):
123 myprj(aProj),
124 mylastzoom(0.0),
125 mysensmode(StdSelect_SM_WINDOW),
126 mypixtol(2),
127 myupdatetol(Standard_True)
128 {
129   for (Standard_Integer i=0;i<=13;i++) {mycoeff [i] = 0.;myprevcoeff[i]=0.0;}
130   for (Standard_Integer j=0;j<2;j++) {mycenter [j] = 0.;myprevcenter[j]=0.0;}
131 }
132
133 //==================================================
134 // Function: Convert
135 // Purpose :
136 //==================================================
137
138 void StdSelect_ViewerSelector3d::Convert(const Handle(SelectMgr_Selection)& aSel)
139 {
140   for(aSel->Init();aSel->More();aSel->Next())
141   {
142     if(aSel->Sensitive()->NeedsConversion())
143     {
144       Handle(Select3D_SensitiveEntity) SE = *((Handle(Select3D_SensitiveEntity)*) &(aSel->Sensitive()));
145       SE->Project(myprj);
146       if(!tosort) tosort=Standard_True;
147     }
148   }
149 }
150
151 //==================================================
152 // Function: Set
153 // Purpose :
154 //==================================================
155
156 void StdSelect_ViewerSelector3d
157 ::Set(const Handle(Select3D_Projector)& aProj)
158 {
159   myprj = aProj;
160   toupdate=Standard_True;
161 }
162
163 //==================================================
164 // Function: SetSensitivityMode
165 // Purpose :
166 //==================================================
167
168 void StdSelect_ViewerSelector3d
169 ::SetSensitivityMode(const StdSelect_SensitivityMode aMode)
170 {
171   mysensmode = aMode;
172   toupdate = Standard_True;
173 }
174
175 //==================================================
176 // Function: SetPixelTolerance
177 // Purpose :
178 //==================================================
179
180 void StdSelect_ViewerSelector3d
181 ::SetPixelTolerance(const Standard_Integer aTolerance)
182 {
183   if(mypixtol!=aTolerance)
184   {
185     mypixtol    = aTolerance;
186     myupdatetol = Standard_True;
187   }
188 }
189
190 //==================================================
191 // Function: SelectPix
192 // Purpose :
193 //==================================================
194
195 void StdSelect_ViewerSelector3d
196 ::Pick(const Standard_Integer XPix,
197        const Standard_Integer YPix,
198        const Handle(V3d_View)& aView)
199 {
200   UpdateProj(aView);
201   Standard_Real Xr3d,Yr3d,Zr3d;
202   gp_Pnt2d P2d;
203   aView->Convert(XPix,YPix,Xr3d,Yr3d,Zr3d);
204   myprj->Project(gp_Pnt(Xr3d,Yr3d,Zr3d),P2d);
205
206   // compute depth limits if clipping plane(s) enabled
207   gp_Lin anEyeLine = myprj->Shoot (P2d.X(), P2d.Y());
208   Standard_Real aPlaneA, aPlaneB, aPlaneC, aPlaneD;
209   Standard_Real aDepthFrom = ShortRealFirst();
210   Standard_Real aDepthTo   = ShortRealLast();
211   for (aView->InitActivePlanes(); aView->MoreActivePlanes(); aView->NextActivePlanes())
212   {
213     aView->ActivePlane()->Plane (aPlaneA, aPlaneB, aPlaneC, aPlaneD);
214     const gp_Dir& anEyeLineDir  = anEyeLine.Direction();
215     gp_Dir aPlaneNormal (aPlaneA, aPlaneB, aPlaneC);
216
217     Standard_Real aDotProduct = anEyeLineDir.Dot (aPlaneNormal);
218     Standard_Real aDirection = -(aPlaneD + anEyeLine.Location().XYZ().Dot (aPlaneNormal.XYZ()));
219     if (Abs (aDotProduct) < Precision::Angular())
220     {
221       // eyeline parallel to the clipping plane
222       if (aDirection > 0.0)
223       {
224         // invalidate the interval
225         aDepthTo   = ShortRealFirst();
226         aDepthFrom = ShortRealFirst();
227         break;
228       }
229       // just ignore this plane
230       continue;
231     }
232
233     // compute distance along the eyeline from eyeline location to intersection with clipping plane
234     Standard_Real aDepth = aDirection / aDotProduct;
235
236     // reduce depth limits
237     if (aDotProduct < 0.0)
238     {
239       if (aDepth < aDepthTo)
240       {
241         aDepthTo = aDepth;
242       }
243     }
244     else if (aDepth > aDepthFrom)
245     {
246       aDepthFrom = aDepth;
247     }
248   }
249   myprj->DepthMinMax (aDepthFrom, aDepthTo);
250
251   InitSelect(P2d.X(),P2d.Y());
252 }
253
254
255 //==================================================
256 // Function: InitSelect
257 // Purpose :
258 //==================================================
259
260 void StdSelect_ViewerSelector3d
261 ::Pick(const Standard_Integer XPMin,
262        const Standard_Integer YPMin,
263        const Standard_Integer XPMax,
264        const Standard_Integer YPMax,
265        const Handle(V3d_View)& aView)
266 {
267   if (myupdatetol && SensitivityMode() == StdSelect_SM_WINDOW)
268   {
269     SetSensitivity (aView->Convert (mypixtol));
270     myupdatetol = Standard_False;
271   }
272   UpdateProj (aView);
273
274   Standard_Real x1,y1,z1,x2,y2,z2;
275   gp_Pnt2d P2d_1,P2d_2;
276   aView->Convert(XPMin,YPMin,x1,y1,z1);
277   aView->Convert(XPMax,YPMax,x2,y2,z2);
278   myprj->Project(gp_Pnt(x1,y1,z1),P2d_1);
279   myprj->Project(gp_Pnt(x2,y2,z2),P2d_2);
280
281   InitSelect (Min(P2d_1.X(),P2d_2.X()),
282               Min(P2d_1.Y(),P2d_2.Y()),
283               Max(P2d_1.X(),P2d_2.X()),
284               Max(P2d_1.Y(),P2d_2.Y()));
285 }
286
287 //==================================================
288 // Function: Pick
289 // Purpose : Selection using a polyline
290 //==================================================
291
292 void StdSelect_ViewerSelector3d::Pick(const TColgp_Array1OfPnt2d& aPolyline, const Handle(V3d_View)& aView)
293 {
294   if (myupdatetol && SensitivityMode() == StdSelect_SM_WINDOW)
295   {
296     SetSensitivity (aView->Convert (mypixtol));
297     myupdatetol = Standard_False;
298   }
299
300   UpdateProj (aView);
301
302   Standard_Integer NbPix = aPolyline.Length();
303   Standard_Integer i;
304
305   // Convert pixel
306   Handle(TColgp_HArray1OfPnt2d) P2d = 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::DisplayAreas(const Handle(V3d_View)& aView)
332 {
333   if (myupdatetol && SensitivityMode() == StdSelect_SM_WINDOW)
334   {
335     SetSensitivity (aView->Convert (mypixtol));
336     myupdatetol = Standard_False;
337   }
338   UpdateProj(aView);
339   UpdateSort(); // Updates the activated areas
340
341   if(mystruct.IsNull())
342     mystruct = new Graphic3d_Structure(aView->Viewer()->Viewer());
343
344   if(myareagroup.IsNull())
345     myareagroup  = new Graphic3d_Group(mystruct);
346
347   SelectMgr_DataMapIteratorOfDataMapOfIntegerSensitive It(myentities);
348   Handle(Select3D_Projector) prj = StdSelect::GetProjector(aView);
349   prj->SetView(aView);
350
351   Standard_Real xmin,ymin,xmax,ymax;
352   gp_Pnt Pbid;
353   SelectBasics_ListOfBox2d BoxList;
354
355   TColgp_SequenceOfPnt aSeqLines;
356   for (; It.More(); It.Next())
357   {
358     It.Value()->Areas(BoxList);
359     for (SelectBasics_ListIteratorOfListOfBox2d itb (BoxList); itb.More(); itb.Next())
360     {
361       itb.Value().Get (xmin, ymin, xmax, ymax);
362
363       Pbid.SetCoord (xmin - mytolerance, ymin - mytolerance, 0.0);
364       prj->Transform (Pbid, prj->InvertedTransformation());
365           aSeqLines.Append(Pbid);
366
367       Pbid.SetCoord (xmax + mytolerance, ymin - mytolerance, 0.0);
368       prj->Transform (Pbid, prj->InvertedTransformation());
369           aSeqLines.Append(Pbid);
370
371       Pbid.SetCoord (xmax + mytolerance, ymax + mytolerance, 0.0);
372       prj->Transform (Pbid, prj->InvertedTransformation());
373           aSeqLines.Append(Pbid);
374
375       Pbid.SetCoord (xmin - mytolerance, ymax + mytolerance, 0.0);
376       prj->Transform (Pbid, prj->InvertedTransformation());
377           aSeqLines.Append(Pbid);
378     }
379   }
380
381   if (aSeqLines.Length())
382   {
383     Standard_Integer n, np;
384     const Standard_Integer nbl = aSeqLines.Length() / 4;
385     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(5*nbl,nbl);
386     for (np = 1, n=0; n<nbl; n++) {
387       aPrims->AddBound(5);
388       const gp_Pnt &p1 = aSeqLines(np++);
389       aPrims->AddVertex(p1);
390       aPrims->AddVertex(aSeqLines(np++));
391       aPrims->AddVertex(aSeqLines(np++));
392       aPrims->AddVertex(aSeqLines(np++));
393       aPrims->AddVertex(p1);
394     }
395     myareagroup->AddPrimitiveArray(aPrims);
396   }
397
398   myareagroup->SetGroupPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_AQUAMARINE1, Aspect_TOL_DASH, 1.0));
399   myareagroup->Structure()->SetDisplayPriority(10);
400   myareagroup->Structure()->Display();
401
402   if(aView->TransientManagerBeginDraw())
403   {
404     Visual3d_TransientManager::DrawStructure(mystruct);
405     Visual3d_TransientManager::EndDraw();
406   }
407   else
408   {
409     aView->Update();
410   }
411 }
412
413 //==================================================
414 // Function: ClearAreas
415 // Purpose :
416 //==================================================
417
418 void StdSelect_ViewerSelector3d::ClearAreas(const Handle(V3d_View)& aView)
419 {
420   if(myareagroup.IsNull()) return;
421   myareagroup->Clear();
422   if(aView.IsNull()) return;
423   if(aView->TransientManagerBeginDraw())
424     Visual3d_TransientManager::EndDraw();
425   else
426     aView->Update();
427 }
428
429 //==================================================
430 // Function: updateproj
431 // Purpose : at any time verifies that
432 //           the view coefficients did not change :
433 // store current view coeffts
434 //        in static array cf [ 0->2 At coordinates XAT YAT ZAT
435 //                            3->5 Up coordinates XUP YUP ZUP
436 //                            6->8 ProjVect coordinates DX DY DZ
437 //                             9   focale
438 //                            10   1. if pers 0. else
439 //==================================================
440
441 Standard_Boolean StdSelect_ViewerSelector3d::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
562   for (; It.More(); It.Next())
563   {
564     if (It.Value()==0)
565     {
566       const Handle(SelectMgr_Selection)& Sel = It.Key();
567       ComputeSensitivePrs(Sel);
568     }
569   }
570
571   mysensgroup->Structure()->SetDisplayPriority(10);
572   mystruct->Display();
573   if (aViou->TransientManagerBeginDraw())
574   {
575     Visual3d_TransientManager::DrawStructure(mystruct);
576     Visual3d_TransientManager::EndDraw();
577   }
578   else if (!aViou.IsNull())
579   {
580     aViou->Update();
581   }
582 }
583
584 //=============================
585 // Function: ClearSensitive
586 // Purpose :
587 //=============================
588 void StdSelect_ViewerSelector3d::ClearSensitive(const Handle(V3d_View)& aViou)
589 {
590   if(mysensgroup.IsNull()) return;
591   mysensgroup->Clear();
592   if(aViou.IsNull()) return;
593
594   if(aViou->TransientManagerBeginDraw())
595     Visual3d_TransientManager::EndDraw();
596   else
597     aViou->Update();
598 }
599
600 //=======================================================================
601 //function : DisplaySenstive
602 //purpose  :
603 //=======================================================================
604 void StdSelect_ViewerSelector3d::
605 DisplaySensitive (const Handle(SelectMgr_Selection)& Sel,
606                   const Handle(V3d_View)& aViou,
607                   const Standard_Boolean ClearOthers)
608 {
609   if (mystruct.IsNull())
610     mystruct = new Graphic3d_Structure (aViou->Viewer()->Viewer());
611   if (mysensgroup.IsNull())
612   {
613     mysensgroup = new Graphic3d_Group (mystruct);
614     Quantity_Color Col (Quantity_NOC_INDIANRED3);
615     Handle(Graphic3d_AspectMarker3d) AM =
616       new Graphic3d_AspectMarker3d (Aspect_TOM_O_PLUS, Col, 2.0);
617     mysensgroup-> SetPrimitivesAspect (AM);
618     mysensgroup->SetPrimitivesAspect (
619       new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
620   }
621
622   if(ClearOthers) mysensgroup->Clear();
623
624   ComputeSensitivePrs(Sel);
625
626   mystruct->SetDisplayPriority(10);
627   mystruct->Display();
628   if(aViou->TransientManagerBeginDraw())
629   {
630     Visual3d_TransientManager::DrawStructure(mystruct);
631     Visual3d_TransientManager::EndDraw();
632   }
633   else if(!aViou.IsNull())
634   {
635     aViou->Update();
636   }
637 }
638
639 //=======================================================================
640 //function : DisplayAreas
641 //purpose  :
642 //=======================================================================
643
644 void StdSelect_ViewerSelector3d::
645 DisplayAreas (const Handle(SelectMgr_Selection)& Sel,
646               const Handle(V3d_View)& aViou,
647               const Standard_Boolean ClearOthers)
648 {
649   if (mystruct.IsNull())
650     mystruct = new Graphic3d_Structure (aViou->Viewer()->Viewer());
651
652   if (mysensgroup.IsNull())
653   {
654     myareagroup = new Graphic3d_Group (mystruct);
655     myareagroup->SetGroupPrimitivesAspect(new Graphic3d_AspectLine3d (Quantity_NOC_AQUAMARINE1, Aspect_TOL_DASH, 1.0));
656   }
657
658   if(ClearOthers) myareagroup->Clear();
659
660   ComputeAreasPrs(Sel);
661
662   mystruct->SetDisplayPriority(10);
663   mystruct->Display();
664
665   if(aViou->TransientManagerBeginDraw())
666   {
667     Visual3d_TransientManager::DrawStructure(mystruct);
668     Visual3d_TransientManager::EndDraw();
669   }
670   else
671   {
672     aViou->Update();
673   }
674 }
675
676 //=======================================================================
677 //function : ComputeSensitivePrs
678 //purpose  :
679 //=======================================================================
680
681 void StdSelect_ViewerSelector3d::ComputeSensitivePrs(const Handle(SelectMgr_Selection)& Sel)
682 {
683   TColgp_SequenceOfPnt aSeqLines, aSeqFree;
684   TColStd_SequenceOfInteger aSeqBnds;
685
686   for(Sel->Init();Sel->More();Sel->Next())
687   {
688     Handle(Select3D_SensitiveEntity) Ent = Handle(Select3D_SensitiveEntity)::DownCast(Sel->Sensitive());
689     const Standard_Boolean hasloc = (Ent.IsNull()? Standard_False : Ent->HasLocation());
690
691     TopLoc_Location theloc;
692     if(hasloc)
693       theloc = Ent->Location();
694
695     //==============
696     // Box
697     //=============
698
699     if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveBox))
700     {
701       const Bnd_Box& B = Handle(Select3D_SensitiveBox)::DownCast (Ent)->Box();
702       Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
703       B.Get (xmin, ymin, zmin, xmax, ymax, zmax);
704       Standard_Integer i;
705       gp_Pnt theboxpoint[8] =
706       {
707         gp_Pnt(xmin,ymin,zmin),
708         gp_Pnt(xmax,ymin,zmin),
709         gp_Pnt(xmax,ymax,zmin),
710         gp_Pnt(xmin,ymax,zmin),
711         gp_Pnt(xmin,ymin,zmax),
712         gp_Pnt(xmax,ymin,zmax),
713         gp_Pnt(xmax,ymax,zmax),
714         gp_Pnt(xmin,ymax,zmax)
715       };
716       if(hasloc)
717       {
718         for (i = 0; i <= 7; i++)
719           theboxpoint[i].Transform (theloc.Transformation());
720       }
721
722       aSeqBnds.Append(5);
723       for (i = 0; i < 4; i++)
724         aSeqLines.Append(theboxpoint[i]);
725       aSeqLines.Append(theboxpoint[0]);
726
727       aSeqBnds.Append(5);
728       for (i = 4; i < 8; i++)
729         aSeqLines.Append(theboxpoint[i]);
730       aSeqLines.Append(theboxpoint[4]);
731
732       for (i = 0; i < 4; i++)
733       {
734         aSeqBnds.Append(2);
735         aSeqLines.Append(theboxpoint[i]);
736         aSeqLines.Append(theboxpoint[i+4]);
737       }
738     }
739     //==============
740     // Face
741     //=============
742     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveFace))
743     {
744       Handle(Select3D_SensitiveFace) aFace = Handle(Select3D_SensitiveFace)::DownCast(Ent);
745       Handle(TColgp_HArray1OfPnt) TheHPts;
746       aFace->Points3D(TheHPts);
747       const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
748
749       aSeqBnds.Append(ThePts.Length());
750       for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
751       {
752         if (hasloc)
753           aSeqLines.Append(ThePts(I).Transformed (theloc.Transformation()));
754         else
755           aSeqLines.Append(ThePts(I));
756       }
757     }
758     //==============
759     // Curve
760     //=============
761     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCurve))
762     {
763       Handle(Select3D_SensitiveCurve) aCurve = Handle(Select3D_SensitiveCurve)::DownCast(Ent);
764       Handle(TColgp_HArray1OfPnt) TheHPts;
765       aCurve->Points3D(TheHPts);
766       const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
767
768       aSeqBnds.Append(ThePts.Length());
769       for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
770       {
771         if (hasloc)
772           aSeqLines.Append(ThePts(I).Transformed (theloc.Transformation()));
773         else
774           aSeqLines.Append(ThePts(I));
775       }
776     }
777     //==============
778     // Wire
779     //=============
780     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveWire))
781     {
782       Handle(Select3D_SensitiveWire) aWire = Handle(Select3D_SensitiveWire)::DownCast(Ent);
783       Select3D_SensitiveEntitySequence EntitySeq;
784       aWire->GetEdges (EntitySeq);
785
786       for (int i = 1; i <= EntitySeq.Length(); i++)
787       {
788         Handle(Select3D_SensitiveEntity) SubEnt = Handle(Select3D_SensitiveEntity)::DownCast(EntitySeq.Value(i));
789
790         //Segment
791         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveSegment))
792         {
793           gp_Pnt P1 (Handle(Select3D_SensitiveSegment)::DownCast(SubEnt)->StartPoint().XYZ());
794           gp_Pnt P2 (Handle(Select3D_SensitiveSegment)::DownCast(SubEnt)->EndPoint().XYZ());
795           if (hasloc)
796           {
797             P1.Transform(theloc.Transformation());
798             P2.Transform(theloc.Transformation());
799           }
800           aSeqBnds.Append(2);
801           aSeqLines.Append(P1);
802           aSeqLines.Append(P2);
803         }
804
805         //circle
806         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCircle))
807         {
808           Handle(Select3D_SensitiveCircle) C = Handle(Select3D_SensitiveCircle)::DownCast(SubEnt);
809           Standard_Integer Lo, Up;
810           C->ArrayBounds (Lo, Up);
811           Standard_Integer II = Lo;
812           while (II <= Up - 2)
813           {
814             gp_Pnt ThePts[3] =
815             {
816               gp_Pnt (C->GetPoint3d (II).XYZ()),
817               gp_Pnt (C->GetPoint3d (++II).XYZ()),
818               gp_Pnt (C->GetPoint3d (++II).XYZ())
819             };
820
821             if (hasloc)
822             {
823               for (Standard_Integer jj = 0; jj <= 2; jj++)
824                 ThePts[jj].Transform (theloc.Transformation());
825             }
826
827             aSeqBnds.Append(4);
828             aSeqLines.Append(ThePts[0]);
829             aSeqLines.Append(ThePts[1]);
830             aSeqLines.Append(ThePts[2]);
831             aSeqLines.Append(ThePts[0]);
832           }
833         }
834
835         //curve
836         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCurve))
837         {
838           Handle(Select3D_SensitiveCurve) aCurve = Handle(Select3D_SensitiveCurve)::DownCast(SubEnt);
839           Handle(TColgp_HArray1OfPnt) TheHPts;
840           aCurve->Points3D (TheHPts);
841           const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
842
843           aSeqBnds.Append(ThePts.Length());
844           for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
845           {
846             if (hasloc)
847               aSeqLines.Append(ThePts(I).Transformed (theloc.Transformation()));
848             else
849               aSeqLines.Append(ThePts(I));
850           }
851         }
852       }
853     }
854     //==============
855     // Segment
856     //=============
857     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveSegment))
858     {
859       gp_Pnt P1 (Handle(Select3D_SensitiveSegment)::DownCast(Ent)->StartPoint().XYZ());
860       gp_Pnt P2 (Handle(Select3D_SensitiveSegment)::DownCast(Ent)->EndPoint().XYZ());
861       if (hasloc)
862       {
863         P1.Transform (theloc.Transformation());
864         P2.Transform (theloc.Transformation());
865       }
866       aSeqBnds.Append(2);
867       aSeqLines.Append(P1);
868       aSeqLines.Append(P2);
869     }
870     //==============
871     // Circle
872     //=============
873     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCircle))
874     {
875       Handle(Select3D_SensitiveCircle) C = Handle(Select3D_SensitiveCircle)::DownCast(Ent);
876       Standard_Integer Lo, Up;
877       C->ArrayBounds (Lo, Up);
878       Standard_Integer II = Lo;
879       while (II <= Up - 2)
880       {
881         gp_Pnt ThePts[3] =
882         {
883           gp_Pnt (C->GetPoint3d (II).XYZ()),
884           gp_Pnt (C->GetPoint3d (++II).XYZ()),
885           gp_Pnt (C->GetPoint3d (++II).XYZ())
886         };
887
888         if (hasloc)
889         {
890           for (Standard_Integer jj = 0; jj <= 2; jj++)
891             ThePts[jj].Transform (theloc.Transformation());
892         }
893
894         aSeqBnds.Append(4);
895         aSeqLines.Append(ThePts[0]);
896         aSeqLines.Append(ThePts[1]);
897         aSeqLines.Append(ThePts[2]);
898         aSeqLines.Append(ThePts[0]);
899       }
900     }
901     //==============
902     // Point
903     //=============
904     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitivePoint))
905     {
906       gp_Pnt P = hasloc ?
907         Handle(Select3D_SensitivePoint)::DownCast(Ent)->Point() :
908         Handle(Select3D_SensitivePoint)::DownCast(Ent)->Point().Transformed (theloc.Transformation());
909       Handle(Graphic3d_ArrayOfPoints) anArrayOfPoints = new Graphic3d_ArrayOfPoints (1);
910       anArrayOfPoints->AddVertex (P.X(), P.Y(), P.Z());
911       mysensgroup->AddPrimitiveArray (anArrayOfPoints);
912     }
913     //============================================================
914     // Triangulation : On met un petit offset ves l'interieur...
915     //==========================================================
916     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveTriangulation))
917     {
918       const Handle(Poly_Triangulation)& PT =
919         (*((Handle(Select3D_SensitiveTriangulation)*) &Ent))->Triangulation();
920
921       const Poly_Array1OfTriangle& triangles = PT->Triangles();
922       const TColgp_Array1OfPnt& Nodes = PT->Nodes();
923       Standard_Integer n[3];
924
925       TopLoc_Location iloc, bidloc;
926       if ((*((Handle(Select3D_SensitiveTriangulation)*) &Ent))->HasInitLocation())
927         bidloc = (*((Handle(Select3D_SensitiveTriangulation)*) &Ent))->GetInitLocation();
928
929       if (bidloc.IsIdentity())
930         iloc = theloc;
931       else
932         iloc = theloc * bidloc;
933
934       Standard_Integer i;
935       for (i = 1; i <= PT->NbTriangles(); i++)
936       {
937         triangles (i).Get (n[0], n[1], n[2]);
938         gp_Pnt P1 (Nodes (n[0]).Transformed (iloc));
939         gp_Pnt P2 (Nodes (n[1]).Transformed (iloc));
940         gp_Pnt P3 (Nodes (n[2]).Transformed (iloc));
941         gp_XYZ V1 (P1.XYZ());
942         gp_XYZ V2 (P2.XYZ());
943         gp_XYZ V3 (P3.XYZ());
944         gp_XYZ CDG (P1.XYZ()); CDG += (P2.XYZ()); CDG += (P3.XYZ()); CDG /= 3.0;
945         V1 -= CDG; V2 -= CDG; V3 -= CDG;
946         V1 *= 0.9; V2 *= 0.9; V3 *= 0.9;
947         V1 += CDG; V2 += CDG; V3 += CDG;
948
949         aSeqBnds.Append(4);
950         aSeqLines.Append(gp_Pnt(V1));
951         aSeqLines.Append(gp_Pnt(V2));
952         aSeqLines.Append(gp_Pnt(V3));
953         aSeqLines.Append(gp_Pnt(V1));
954       }
955
956       // recherche des bords libres...
957
958       Handle(TColStd_HArray1OfInteger) FreeEdges = new TColStd_HArray1OfInteger (1, 2 * StdSel_NumberOfFreeEdges (PT));
959       TColStd_Array1OfInteger& FreeE = FreeEdges->ChangeArray1();
960       Poly_Connect pc (PT);
961       Standard_Integer t[3];
962       Standard_Integer j;
963       Standard_Integer fr (1);
964       for (i = 1; i <= PT->NbTriangles(); i++)
965       {
966         pc.Triangles (i, t[0], t[1], t[2]);
967         triangles (i).Get (n[0], n[1], n[2]);
968         for (j = 0; j < 3; j++)
969         {
970           Standard_Integer k = (j + 1) % 3;
971           if (t[j] == 0)
972           {
973             FreeE (fr)    = n[j];
974             FreeE (fr + 1)= n[k];
975             fr += 2;
976           }
977         }
978       }
979       for (Standard_Integer ifri = 1; ifri <= FreeE.Length(); ifri += 2)
980       {
981         gp_Pnt pe1 (Nodes (FreeE (ifri)).Transformed (iloc)), pe2 (Nodes (FreeE (ifri + 1)).Transformed (iloc));
982         aSeqFree.Append(pe1);
983         aSeqFree.Append(pe2);
984       }
985     }
986     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveTriangle))
987     {
988       Handle(Select3D_SensitiveTriangle) Str = Handle(Select3D_SensitiveTriangle)::DownCast(Ent);
989       gp_Pnt P1, P2, P3;
990       Str->Points3D (P1, P2, P3);
991       gp_Pnt CDG = Str->Center3D();
992
993       gp_XYZ V1 (P1.XYZ()); V1 -= (CDG.XYZ());
994       gp_XYZ V2 (P2.XYZ()); V2 -= (CDG.XYZ());
995       gp_XYZ V3 (P3.XYZ()); V3 -= (CDG.XYZ());
996       V1 *= 0.9; V2 *= 0.9; V3 *= 0.9;
997       V1 += CDG.XYZ(); V2 += CDG.XYZ(); V3 += CDG.XYZ();
998
999       aSeqBnds.Append(4);
1000       aSeqLines.Append(gp_Pnt(V1));
1001       aSeqLines.Append(gp_Pnt(V2));
1002       aSeqLines.Append(gp_Pnt(V3));
1003       aSeqLines.Append(gp_Pnt(V1));
1004     }
1005   }
1006
1007   Standard_Integer i;
1008
1009   if (aSeqLines.Length())
1010   {
1011     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(aSeqLines.Length(),aSeqBnds.Length());
1012     for (i = 1; i <= aSeqLines.Length(); i++)
1013       aPrims->AddVertex(aSeqLines(i));
1014     for (i = 1; i <= aSeqBnds.Length(); i++)
1015       aPrims->AddBound(aSeqBnds(i));
1016     myareagroup->AddPrimitiveArray(aPrims);
1017   }
1018
1019   if (aSeqFree.Length())
1020   {
1021     mysensgroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GREEN, Aspect_TOL_SOLID, 2.0));
1022     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(aSeqFree.Length(),aSeqFree.Length()/2);
1023     for (i = 1; i <= aSeqFree.Length(); i++)
1024         {
1025       aPrims->AddBound(2);
1026       aPrims->AddVertex(aSeqLines(i++));
1027       aPrims->AddVertex(aSeqLines(i));
1028         }
1029     mysensgroup->AddPrimitiveArray(aPrims);
1030     mysensgroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
1031   }
1032 }
1033
1034 //=======================================================================
1035 //function : ComputeAreaPrs
1036 //purpose  :
1037 //=======================================================================
1038
1039 void StdSelect_ViewerSelector3d::ComputeAreasPrs (const Handle(SelectMgr_Selection)& Sel)
1040 {
1041   Standard_Real xmin, ymin, xmax, ymax;
1042   gp_Pnt Pbid;
1043   SelectBasics_ListOfBox2d BoxList;
1044
1045   TColgp_SequenceOfPnt aSeqLines;
1046   for (Sel->Init(); Sel->More(); Sel->Next())
1047   {
1048     Sel->Sensitive()->Areas (BoxList);
1049     for (SelectBasics_ListIteratorOfListOfBox2d itb (BoxList); itb.More(); itb.Next())
1050     {
1051       itb.Value().Get (xmin, ymin, xmax, ymax);
1052
1053       Pbid.SetCoord (xmin - mytolerance, ymin - mytolerance, 0.0);
1054       myprj->Transform (Pbid, myprj->InvertedTransformation());
1055       aSeqLines.Append(Pbid);
1056
1057       Pbid.SetCoord (xmax + mytolerance, ymin - mytolerance, 0.0);
1058       myprj->Transform (Pbid, myprj->InvertedTransformation());
1059       aSeqLines.Append(Pbid);
1060
1061       Pbid.SetCoord (xmax + mytolerance, ymax + mytolerance, 0.0);
1062       myprj->Transform (Pbid, myprj->InvertedTransformation());
1063       aSeqLines.Append(Pbid);
1064
1065       Pbid.SetCoord (xmin - mytolerance, ymax + mytolerance, 0.0);
1066       myprj->Transform (Pbid, myprj->InvertedTransformation());
1067       aSeqLines.Append(Pbid);
1068     }
1069   }
1070
1071   if (aSeqLines.Length())
1072   {
1073     Standard_Integer n, np;
1074     const Standard_Integer nbl = aSeqLines.Length() / 4;
1075     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(5*nbl,nbl);
1076     for (np = 1, n=0; n<nbl; n++) {
1077       aPrims->AddBound(5);
1078       const gp_Pnt &p1 = aSeqLines(np++);
1079       aPrims->AddVertex(p1);
1080       aPrims->AddVertex(aSeqLines(np++));
1081       aPrims->AddVertex(aSeqLines(np++));
1082       aPrims->AddVertex(aSeqLines(np++));
1083       aPrims->AddVertex(p1);
1084     }
1085     myareagroup->AddPrimitiveArray(aPrims);
1086   }
1087 }
1088
1089 //=======================================================================
1090 //function : ReactivateProjector
1091 //purpose  :
1092 //=======================================================================
1093 void StdSelect_ViewerSelector3d::ReactivateProjector()
1094 {
1095   Handle(SelectBasics_SensitiveEntity) BS;
1096   for (SelectMgr_DataMapIteratorOfDataMapOfIntegerSensitive it (myentities); it.More(); it.Next())
1097   {
1098     BS = it.Value();
1099     if (BS->Is3D())
1100     {
1101       (*((Handle(Select3D_SensitiveEntity)*) &BS))->SetLastPrj (myprj);
1102     }
1103   }
1104 }