9f5f031a5e3ff160cfdf18dd4c27c46f23c4fbab
[occt.git] / src / Draw / Draw_Viewer.cxx
1 // Created on: 1992-04-06
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1992-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 // Updated by GG Tue Oct 22 16:22:10 1996
18 //              reason : Try to compress the pixel image
19 //                       in PseudoColor 8 planes format
20 //              see : SaveView(filename)
21
22 #include <Draw_Viewer.hxx>
23 #include <Draw_View.hxx>
24
25 #include <gp_Pnt.hxx>
26 #include <gp_Pnt2d.hxx>
27 #include <Draw_Window.hxx>
28 #include <Draw_Display.hxx>
29
30
31 #define precpers 0.95
32 #define ButtonPress 4
33 #define MotionNotify 6
34 static const Standard_Real DRAWINFINITE = 1e50;
35 Standard_EXPORT Standard_Boolean Draw_Bounds = Standard_True;
36 extern Standard_Boolean Draw_Batch;
37 const Standard_Integer MAXSEGMENT = 1000;
38 Segment segm[MAXSEGMENT];
39 static int nbseg=0;
40 static Draw_View* curview = NULL;
41 static Standard_Integer curviewId = 0;
42 static char blank[2] = "";
43 static Standard_Real xmin,xmax,ymin,ymax;
44 static Standard_Boolean found = Standard_False;
45 static Standard_Integer  xpick, ypick, precpick;
46 static gp_Pnt lastPickP1;
47 static gp_Pnt lastPickP2;
48 static Standard_Real   lastPickParam;
49 static Draw_Color highlightcol;
50 static Draw_Color currentcolor;
51 static Standard_Boolean highlight = Standard_False;
52 static Standard_Integer ps_vx, ps_vy;
53 static Standard_Real ps_kx, ps_ky;
54 static Standard_Integer ps_px, ps_py;
55 static ostream* ps_stream;
56 static Standard_Integer ps_width[MAXCOLOR];
57 static Standard_Real    ps_gray[MAXCOLOR];
58
59 enum DrawingMode {DRAW, PICK, POSTSCRIPT};
60 static DrawingMode CurrentMode = DRAW;
61
62 //=======================================================================
63 //function : Create
64 //purpose  :
65 //=======================================================================
66
67 Draw_Viewer::Draw_Viewer()
68 {
69   if (Draw_Batch) return;
70   Standard_Integer i;
71   for ( i = 0; i < MAXVIEW; i++) myViews[i] = NULL;
72   for (i = 0; i < MAXCOLOR; i++) {
73     ps_width[i] = 1;
74     ps_gray[i]  = 0;
75   }
76 }
77
78 //=======================================================================
79 //function : DefineColor
80 //purpose  :
81 //=======================================================================
82
83 Standard_Boolean Draw_Viewer::DefineColor (const Standard_Integer i, const char* colname)
84 {
85   if (Draw_Batch) return 1;
86   return Draw_Window::DefineColor(i,colname);
87 }
88
89
90 //=======================================================================
91 //function : MakeView
92 //purpose  :
93 //=======================================================================
94
95 void Draw_Viewer::MakeView(const Standard_Integer id,
96                            const char* typ,
97                            const Standard_Integer X, const Standard_Integer Y,
98                            const Standard_Integer W, const Standard_Integer H)
99 {
100   if (Draw_Batch) return;
101   if (id < MAXVIEW) {
102
103     DeleteView(id);
104     myViews[id] = new Draw_View(id,this,X , Y, W, H);
105
106     // View fields
107     myViews[id]->SetDx(W / 2);
108     myViews[id]->SetDy(- H / 2);
109
110     if (!myViews[id]->Init(typ))
111       DeleteView(id);
112
113     RepaintView(id);
114   }
115 }
116
117 #ifdef _WIN32
118 //=======================================================================
119 //function : MakeView
120 //purpose  :
121 //=======================================================================
122
123 void Draw_Viewer::MakeView(const Standard_Integer id,
124                            const char* typ,
125                            const Standard_Integer X, const Standard_Integer Y,
126                            const Standard_Integer W, const Standard_Integer H,
127          HWND win, Standard_Boolean useBuffer)
128 {
129   if (Draw_Batch) return;
130   if (id < MAXVIEW) {
131
132     DeleteView(id);
133     myViews[id] = new Draw_View(id, this, X, Y, W, H, win);
134     myViews[id]->SetUseBuffer(useBuffer);
135
136     // View fields
137     myViews[id]->SetDx( W / 2);
138     myViews[id]->SetDy(-H / 2);
139
140     if (!myViews[id]->Init(typ))
141       DeleteView(id);
142     RepaintView(id);
143   }
144 }
145 #endif
146
147 //=======================================================================
148 //function : MakeView
149 //purpose  :
150 //=======================================================================
151
152 void Draw_Viewer::MakeView    (const Standard_Integer id,
153                                const char*  typ,
154                                const char*  window)
155 {
156   if (Draw_Batch) return;
157   if (id < MAXVIEW) {
158
159     DeleteView(id);
160     myViews[id] = new Draw_View(id,this,window);
161
162
163     myViews[id]->SetDx(myViews[id]->WidthWin() / 2);
164     myViews[id]->SetDy(-myViews[id]->HeightWin() / 2);
165
166     if (!myViews[id]->Init(typ))
167       DeleteView(id);
168
169     RepaintView(id);
170   }
171 }
172
173
174 //=======================================================================
175 //function : SetTitle
176 //purpose  :
177 //=======================================================================
178
179 void Draw_Viewer::SetTitle (const Standard_Integer id, const char* name)
180 {
181   if (Draw_Batch) return;
182   if(myViews[id]) myViews[id]->SetTitle((char*)name);
183 }
184
185 //=======================================================================
186 //function : ResetView
187 //purpose  : reset view zoom and axes
188 //=======================================================================
189
190 void Draw_Viewer::ResetView(const Standard_Integer id)
191 {
192   if (Draw_Batch) return;
193   if (myViews[id]) {
194     myViews[id]->Init(myViews[id]->Type());
195     ConfigView(id);
196   }
197 }
198
199 //=======================================================================
200 //function : SetZoom
201 //purpose  :
202 //=======================================================================
203
204 void Draw_Viewer::SetZoom (const Standard_Integer id, const Standard_Real z)
205 {
206   if (Draw_Batch)
207     return;
208
209   Draw_View* aView = myViews[id];
210   if (aView)
211   {
212     Standard_Real zz = z / aView->GetZoom();
213     aView->SetZoom(z);
214     Standard_Integer X,Y,W,H;
215     GetPosSize(id,X,Y,W,H);
216
217     const Standard_Real w = 0.5 * static_cast<Standard_Real>(W);
218     const Standard_Real h = 0.5 * static_cast<Standard_Real>(H);
219
220     const Standard_Integer aDx = static_cast<Standard_Integer>
221       (  w - zz * (w - aView->GetDx()) );
222     const Standard_Integer aDy = static_cast<Standard_Integer>
223       ( -h + zz * (h + aView->GetDy()) );
224
225     aView->SetDx(aDx);
226     aView->SetDy(aDy);
227   }
228 }
229
230 //=======================================================================
231 //function : RotateView
232 //purpose  :
233 //=======================================================================
234
235 void   Draw_Viewer::RotateView  (const Standard_Integer id,
236                                  const gp_Dir2d& D,
237                                  const Standard_Real A)
238 {
239   if (Draw_Batch) return;
240   if (myViews[id]) {
241     gp_Trsf T = myViews[id]->GetMatrix();
242
243     T.Invert();
244     gp_Pnt PP(0,0,0);
245     gp_Dir DD(D.X(),D.Y(),0);
246     PP.Transform(T);
247     DD.Transform(T);
248     RotateView(id,PP,DD,A);
249   }
250 }
251
252 //=======================================================================
253 //function : RotateView
254 //purpose  :
255 //=======================================================================
256
257 void   Draw_Viewer::RotateView  (const Standard_Integer id,
258                                  const gp_Pnt& P,
259                                  const gp_Dir& D,
260                                  const Standard_Real A)
261 {
262   if (Draw_Batch) return;
263   if (myViews[id]) {
264     gp_Trsf T;
265     T.SetRotation(gp_Ax1(P,D),A);
266     myViews[id]->Transform(T);
267   }
268 }
269
270
271 //=======================================================================
272 //function : SetFocal
273 //purpose  :
274 //=======================================================================
275
276 void Draw_Viewer::SetFocal (const Standard_Integer id, const Standard_Real F)
277 {
278   if (Draw_Batch) return;
279   if (myViews[id])
280     myViews[id]->SetFocalDistance(F);
281 }
282
283 //=======================================================================
284 //function : GetType
285 //purpose  :
286 //=======================================================================
287
288 char* Draw_Viewer::GetType (const Standard_Integer id) const
289 {
290   if (Draw_Batch) return blank;
291   if (myViews[id])
292     return const_cast<char*>(myViews[id]->Type());
293   else
294     return blank;
295 }
296
297 //=======================================================================
298 //function : Zoom
299 //purpose  :
300 //=======================================================================
301
302 Standard_Real Draw_Viewer::Zoom (const Standard_Integer id) const
303 {
304   if (Draw_Batch) return Standard_False;
305   if (myViews[id])
306     return myViews[id]->GetZoom();
307   else
308     return 0.0;
309 }
310
311 //=======================================================================
312 //function : Focal
313 //purpose  :
314 //=======================================================================
315
316 Standard_Real Draw_Viewer::Focal (const Standard_Integer id) const
317 {
318   if (Draw_Batch) return 1.;
319   if (myViews[id])
320     return myViews[id]->GetFocalDistance();
321   else
322     return 0;
323 }
324
325 //=======================================================================
326 //function : GetTrsf
327 //purpose  :
328 //=======================================================================
329
330 void Draw_Viewer::GetTrsf (const Standard_Integer id,gp_Trsf& T) const
331 {
332   if (Draw_Batch) return;
333   if (myViews[id])
334     T = myViews[id]->GetMatrix();
335 }
336
337 //=======================================================================
338 //function : Is3D
339 //purpose  :
340 //=======================================================================
341
342 Standard_Boolean Draw_Viewer::Is3D (const Standard_Integer id) const
343 {
344   if (Draw_Batch) return Standard_False;
345   if (myViews[id])
346     return !myViews[id]->Is2D();
347   else
348     return Standard_False;
349 }
350
351 //=======================================================================
352 //function : SetTrsf
353 //purpose  :
354 //=======================================================================
355
356 void Draw_Viewer::SetTrsf (const Standard_Integer id,gp_Trsf& T)
357 {
358   if (Draw_Batch) return;
359   if (myViews[id])
360     myViews[id]->SetMatrix(T);
361 }
362
363 //=======================================================================
364 //function : GetPosSize
365 //purpose  :
366 //=======================================================================
367
368 void Draw_Viewer::GetPosSize(const Standard_Integer id,
369                              Standard_Integer& X, Standard_Integer& Y,
370                              Standard_Integer& W, Standard_Integer& H)
371 {
372   if (Draw_Batch) return;
373   if (myViews[id] != NULL) {
374     myViews[id]->GetPosition(X, Y);
375     W = myViews[id]->WidthWin();
376     H = myViews[id]->HeightWin();
377   }
378 }
379
380 //=======================================================================
381 //function : GetFrame
382 //purpose  :
383 //=======================================================================
384
385 void Draw_Viewer::GetFrame(const Standard_Integer id,
386                            Standard_Integer& xminf, Standard_Integer& yminf,
387                            Standard_Integer& xmaxf, Standard_Integer& ymaxf)
388 {
389   if (Draw_Batch) return;
390   if (myViews[id]) {
391     Standard_Integer X,Y,H,W;
392     GetPosSize(id,X,Y,W,H);
393     xminf =   - myViews[id]->GetDx();
394     xmaxf = W - myViews[id]->GetDx();
395     yminf =   - myViews[id]->GetDy() - H;
396     ymaxf =   - myViews[id]->GetDy();
397   }
398 }
399
400 //=======================================================================
401 //function : FitView
402 //purpose  :
403 //=======================================================================
404
405 void Draw_Viewer::FitView(const Standard_Integer id, const Standard_Integer frame)
406 {
407   if (Draw_Batch) return;
408   if (myViews[id]) {
409
410     // is this the only view in its category
411     Standard_Boolean is2d = myViews[id]->Is2D();
412     Standard_Integer i,nbviews = 0;
413     for (i = 1; i < MAXVIEW; i++) {
414       if (myViews[i]) {
415         if (myViews[i]->Is2D() == is2d)
416           ++nbviews;
417       }
418     }
419     Standard_Boolean only = (nbviews == 1);
420
421     Standard_Integer X,Y,H,W;
422     GetPosSize(id,X,Y,W,H);
423     // compute the min max
424     Standard_Integer n = myDrawables.Length();
425     if (n == 0) return;
426 //    Draw_Display DF;
427     curview = myViews[id];
428     Standard_Real umin,umax,vmin,vmax;
429     Standard_Real u1,u2,v1,v2;
430     umin = vmin = DRAWINFINITE;
431     umax = vmax = -DRAWINFINITE;
432
433     for (i = 1; i <= n; i++) {
434       Standard_Boolean d3d = myDrawables(i)->Is3D();
435       if ((d3d && !is2d) || (!d3d && is2d)) {
436         // if this is not the only view recompute...
437         if (!only)
438           DrawOnView(id,myDrawables(i));
439         myDrawables(i)->Bounds(u1,u2,v1,v2);
440         if (u1 < umin) umin = u1;
441         if (u2 > umax) umax = u2;
442         if (v1 < vmin) vmin = v1;
443         if (v2 > vmax) vmax = v2;
444       }
445     }
446     Standard_Real z;
447     umin = umin / curview->GetZoom();
448     vmin = vmin / curview->GetZoom();
449     umax = umax / curview->GetZoom();
450     vmax = vmax / curview->GetZoom();
451     if ((umax - umin) < 1.e-6) {
452       if ((vmax - vmin) < 1.e-6)
453         return;
454       else
455         z = ((Standard_Real)(H - 2*frame)) / (vmax - vmin);
456     }
457     else {
458       z = ((Standard_Real)(W - 2*frame)) /((Standard_Real) (umax - umin));
459       if ((vmax - vmin) > 1.e-6) {
460         Standard_Real z2 = ((Standard_Real)(H - 2*frame)) /(vmax - vmin);
461         if (z2 < z) z = z2;
462       }
463     }
464     curview->SetZoom(z);
465     curview->SetDx( static_cast<Standard_Integer>( W / 2 - 0.5 * (umin+umax) * z) );
466     curview->SetDy( static_cast<Standard_Integer>(-H / 2 - 0.5 * (vmin+vmax) * z) );
467   }
468 }
469
470 //=======================================================================
471 //function : PanView
472 //purpose  :
473 //=======================================================================
474
475 void Draw_Viewer::PanView(const Standard_Integer id,
476                           const Standard_Integer DX, const Standard_Integer DY)
477 {
478   if (Draw_Batch) return;
479   if (myViews[id]) {
480     myViews[id]->SetDx(myViews[id]->GetDx() + DX);
481     myViews[id]->SetDy(myViews[id]->GetDy() + DY);
482   }
483 }
484
485
486 //=======================================================================
487 //function : SetPan
488 //purpose  :
489 //=======================================================================
490
491 void Draw_Viewer::SetPan(const Standard_Integer id,
492                          const Standard_Integer DX, const Standard_Integer DY)
493 {
494   if (Draw_Batch) return;
495   if (myViews[id]) {
496     myViews[id]->SetDx(DX);
497     myViews[id]->SetDy(DY);
498   }
499 }
500
501 //=======================================================================
502 //function : GetPan
503 //purpose  :
504 //=======================================================================
505
506 void Draw_Viewer::GetPan(const Standard_Integer id,
507                          Standard_Integer& DX, Standard_Integer& DY)
508 {
509   if (Draw_Batch) return;
510   if (myViews[id]) {
511     DX = myViews[id]->GetDx();
512     DY = myViews[id]->GetDy();
513   }
514 }
515
516 //=======================================================================
517 //function : HasView
518 //purpose  :
519 //=======================================================================
520
521 Standard_Boolean Draw_Viewer::HasView(const Standard_Integer id) const
522 {
523   if (Draw_Batch) return Standard_False;
524   if ((id < 0) || id >= MAXVIEW) return Standard_False;
525   return myViews[id] != NULL;
526 }
527
528 //=======================================================================
529 //function : DisplayView
530 //purpose  :
531 //=======================================================================
532
533 void Draw_Viewer::DisplayView (const Standard_Integer id) const
534 {
535   if (Draw_Batch) return;
536   if (myViews[id]) myViews[id]->DisplayWindow();
537 }
538
539 //=======================================================================
540 //function : HideView
541 //purpose  :
542 //=======================================================================
543
544 void Draw_Viewer::HideView (const Standard_Integer id) const
545 {
546   if (Draw_Batch) return;
547   if (myViews[id]) {
548     //
549   }
550 }
551
552 //=======================================================================
553 //function : ClearView
554 //purpose  :
555 //=======================================================================
556
557 void Draw_Viewer::ClearView(const Standard_Integer id) const
558 {
559   if (Draw_Batch) return;
560   if (myViews[id]) myViews[id]->Clear();
561 }
562
563 //=======================================================================
564 //function : RemoveView
565 //purpose  :
566 //=======================================================================
567
568 void Draw_Viewer::RemoveView(const Standard_Integer id)
569 {
570   if (Draw_Batch) return;
571   if (myViews[id]) {
572     delete myViews[id];
573     myViews[id] = NULL;
574   }
575 }
576
577 //=======================================================================
578 //function : RepaintView
579 //purpose  :
580 //=======================================================================
581 void Draw_Viewer::RepaintView (const Standard_Integer id) const
582 {
583   if (Draw_Batch) return;
584   if (myViews[id]) {
585     ClearView(id);
586     Standard_Integer n = myDrawables.Length();
587     for (Standard_Integer i = 1; i <= n; i++)
588       DrawOnView(id,myDrawables(i));
589   }
590 }
591
592
593 #ifdef _WIN32
594 //=======================================================================
595 //function : ResizeView
596 //purpose  : WNT re-drawing optimization
597 //=======================================================================
598 void Draw_Viewer::ResizeView (const Standard_Integer id) const
599 {
600   if (Draw_Batch) return;
601   if (myViews[id] && myViews[id]->GetUseBuffer()) {
602     myViews[id]->InitBuffer();
603     RepaintView(id);
604   }
605 }
606
607 //=======================================================================
608 //function : UpdateView
609 //purpose  : WNT re-drawing optimization
610 //=======================================================================
611 void Draw_Viewer::UpdateView (const Standard_Integer id, const Standard_Boolean forced) const
612 {
613   if (Draw_Batch) return;
614   if (myViews[id]) {
615     if (!myViews[id]->GetUseBuffer() || forced) {
616       RepaintView(id);
617     }
618     // Fast redrawing on WNT
619     if (myViews[id]->GetUseBuffer()) myViews[id]->Redraw();
620   }
621 }
622 #endif
623
624 //=======================================================================
625 //function : ConfigView
626 //purpose  :
627 //=======================================================================
628
629 void Draw_Viewer::ConfigView (const Standard_Integer id) const
630 {
631   if (Draw_Batch) return;
632   if (myViews[id])
633   {
634     myViews[id]->SetDx(myViews[id]->WidthWin()   / 2);
635     myViews[id]->SetDy(-myViews[id]->HeightWin() / 2);
636   }
637 }
638
639 //=======================================================================
640 //function : PostScriptView
641 //purpose  :
642 //=======================================================================
643
644 void Draw_Viewer::PostScriptView (const Standard_Integer id,
645                                   const Standard_Integer VXmin,
646                                   const Standard_Integer VYmin,
647                                   const Standard_Integer VXmax,
648                                   const Standard_Integer VYmax,
649                                   const Standard_Integer PXmin,
650                                   const Standard_Integer PYmin,
651                                   const Standard_Integer PXmax,
652                                   const Standard_Integer PYmax,
653                                   ostream& sortie) const
654 {
655   if (Draw_Batch) return;
656   if (myViews[id]) {
657     ps_vx = VXmin;
658     ps_vy = VYmin;
659     ps_px = PXmin;
660     ps_py = PYmin;
661     ps_kx = ((Standard_Real) (PXmax - PXmin)) / ((Standard_Real) (VXmax - VXmin));
662     ps_ky = ((Standard_Real) (PYmax - PYmin)) / ((Standard_Real) (VYmax - VYmin));
663     ps_stream = &sortie;
664     Standard_Integer n = myDrawables.Length();
665     if (n == 0) return;
666     CurrentMode = POSTSCRIPT;
667     Draw_Display DF = MakeDisplay(id);
668     Standard_Boolean view2d = myViews[id]->Is2D();
669     for (Standard_Integer i = 1; i <= n; i++)
670       if (myDrawables(i)->Is3D()) {
671         if (!view2d) myDrawables(i)->DrawOn(DF);
672       }
673     else {
674       if (view2d) myDrawables(i)->DrawOn(DF);
675     }
676     sortie << "stroke\n";
677     CurrentMode = DRAW;
678   }
679 }
680
681 //=======================================================================
682 //function : PostColor
683 //purpose  :
684 //=======================================================================
685
686 void Draw_Viewer::PostColor(const Standard_Integer icol,
687                             const Standard_Integer width,
688                             const Standard_Real    gray)
689 {
690   if (Draw_Batch) return;
691   if ((icol < 0) || (icol >= MAXCOLOR)) return;
692   ps_width[icol] = width;
693   ps_gray[icol] = gray;
694 }
695
696 //=======================================================================
697 //function : SaveView
698 //purpose  :
699 //=======================================================================
700
701 Standard_Boolean Draw_Viewer::SaveView(const Standard_Integer id,
702                                        const char* filename)
703 {
704   if (Draw_Batch) return Standard_False;;
705   Flush();
706   if (myViews[id]) {
707     return myViews[id]->Save(filename);
708   }
709   else
710   {
711     std::cerr << "View " << id << " doesn't exists!\n";
712     return Standard_False;
713   }
714 }
715
716 //=======================================================================
717 //function : RepaintAll
718 //purpose  :
719 //=======================================================================
720
721 void Draw_Viewer::RepaintAll () const
722 {
723   if (Draw_Batch) return;
724   for (Standard_Integer id = 0; id < MAXVIEW; id++)
725     RepaintView(id);
726 }
727
728 //=======================================================================
729 //function : Repaint2D
730 //purpose  :
731 //=======================================================================
732
733 void Draw_Viewer::Repaint2D () const
734 {
735   if (Draw_Batch) return;
736   for (Standard_Integer id = 0; id < MAXVIEW; id++)
737     if (myViews[id]) {
738       if (myViews[id]->Is2D())
739         RepaintView(id);
740     }
741 }
742
743 //=======================================================================
744 //function : Repaint3D
745 //purpose  :
746 //=======================================================================
747
748 void Draw_Viewer::Repaint3D () const
749 {
750   if (Draw_Batch) return;
751   for (Standard_Integer id = 0; id < MAXVIEW; id++)
752     if (myViews[id]) {
753       if (!myViews[id]->Is2D())
754         RepaintView(id);
755     }
756 }
757
758 //=======================================================================
759 //function : DeleteView
760 //purpose  :
761 //=======================================================================
762
763 void Draw_Viewer::DeleteView(const Standard_Integer id)
764 {
765   if (Draw_Batch) return;
766   if (myViews[id] != NULL) {
767     delete myViews[id];
768     myViews[id] = NULL;
769   }
770 }
771
772 //=======================================================================
773 //function : Clear
774 //purpose  :
775 //=======================================================================
776
777 void Draw_Viewer::Clear()
778 {
779   if (Draw_Batch) return;
780   for (Standard_Integer i = 1; i <= myDrawables.Length(); i++)
781     myDrawables(i)->Visible(Standard_False);
782   myDrawables.Clear();
783   for (Standard_Integer id = 0; id < MAXVIEW; id++)
784     ClearView(id);
785 }
786
787 //=======================================================================
788 //function : Clear2D
789 //purpose  :
790 //=======================================================================
791
792 void Draw_Viewer::Clear2D()
793 {
794   if (Draw_Batch) return;
795   Standard_Integer i = 1;
796   while (i <= myDrawables.Length()) {
797     if (myDrawables(i)->Is3D())
798       i++;
799     else {
800       myDrawables(i)->Visible(Standard_False);
801       myDrawables.Remove(i);
802     }
803   }
804   for (Standard_Integer id = 0; id < MAXVIEW; id++) {
805     if (myViews[id]) {
806       if (myViews[id]->Is2D())
807         ClearView(id);
808     }
809   }
810 }
811
812 //=======================================================================
813 //function : Clear3D
814 //purpose  :
815 //=======================================================================
816
817 void Draw_Viewer::Clear3D()
818 {
819   if (Draw_Batch) return;
820   Standard_Integer i = 1;
821   while (i <= myDrawables.Length()) {
822     if (myDrawables(i)->Is3D()) {
823       myDrawables(i)->Visible(Standard_False);
824       myDrawables.Remove(i);
825     }
826     else
827       i++;
828   }
829   for (Standard_Integer id = 0; id < MAXVIEW; id++) {
830     if (myViews[id]) {
831       if (!myViews[id]->Is2D())
832         ClearView(id);
833     }
834   }
835 }
836
837 //=======================================================================
838 //function : Flush
839 //purpose  :
840 //=======================================================================
841
842 void Draw_Viewer::Flush()
843 {
844   if (Draw_Batch) return;
845   Draw_Window::Flush();
846 }
847
848 //=======================================================================
849 //function : DrawOnView
850 //purpose  :
851 //=======================================================================
852
853 void Draw_Viewer::DrawOnView(const Standard_Integer id,
854                              const Handle(Draw_Drawable3D)& D) const
855 {
856   if (Draw_Batch) return;
857   if (myViews[id]) {
858     Draw_Display d = MakeDisplay(id);
859     xmin = ymin = DRAWINFINITE;
860     xmax = ymax = -DRAWINFINITE;
861
862     Standard_Boolean view2d = myViews[id]->Is2D();
863     myViews[id]->ResetFrame();
864     if ((D->Is3D() && !view2d) || (!D->Is3D() && view2d))
865     {
866       D->DrawOn(d);
867       if (CurrentMode == DRAW)
868         D->SetBounds(xmin,xmax,ymin,ymax);
869       d.Flush();
870     }
871   }
872 }
873
874 //=======================================================================
875 //function : HighlightOnView
876 //purpose  :
877 //=======================================================================
878
879 void Draw_Viewer::HighlightOnView (const Standard_Integer id,
880                                    const Handle(Draw_Drawable3D)& D,
881                                    const Draw_ColorKind C) const
882 {
883   if (Draw_Batch) return;
884   highlight = Standard_True;
885   highlightcol = C;
886   DrawOnView(id,D);
887   highlight = Standard_False;
888 }
889
890 //=======================================================================
891 //function : AddDrawable
892 //purpose  :
893 //=======================================================================
894
895 void Draw_Viewer::AddDrawable (const Handle(Draw_Drawable3D)& D)
896 {
897   if (Draw_Batch) return;
898   if (!D.IsNull() && !D->Visible()) {
899     myDrawables.Append(D);
900     D->Visible(Standard_True);
901   }
902 }
903
904 //=======================================================================
905 //function : RemoveDrawable
906 //purpose  :
907 //=======================================================================
908
909 void Draw_Viewer::RemoveDrawable (const Handle(Draw_Drawable3D)& D)
910 {
911   if (Draw_Batch) return;
912   if (!D.IsNull() && D->Visible()) {
913     Standard_Integer index;
914     for (index = 1; index <= myDrawables.Length(); index++) {
915       if (myDrawables(index) == D) {
916         D->Visible(Standard_False);
917         myDrawables.Remove(index);
918         return;
919       }
920     }
921   }
922 }
923
924 //=======================================================================
925 //function : MakeDisplay
926 //purpose  : return a display on the view
927 //=======================================================================
928
929 Draw_Display Draw_Viewer::MakeDisplay (const Standard_Integer id) const
930 {
931   if (Draw_Batch) {Draw_Display dis;return dis;}
932   curviewId = id;
933   curview = myViews[id];
934   int GXcopy = 0x3;
935   nbseg = 0;
936   Draw_Color initcol(Draw_blanc);
937   // to force setting the color
938   currentcolor = Draw_Color(Draw_rouge);
939   Draw_Display dis;
940   dis.SetColor(initcol);
941   dis.SetMode(GXcopy);
942   return dis;
943 }
944
945 //=======================================================================
946 //function : Select
947 //purpose  :
948 //=======================================================================
949 void Draw_Viewer::Select (Standard_Integer& id, Standard_Integer& X, Standard_Integer& Y,
950                           Standard_Integer& Button, Standard_Boolean wait)
951 {
952   if (Draw_Batch) return;
953   Flush();
954 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
955   if (!wait) {
956     if (id >=0 && id < MAXVIEW) {
957       if (myViews[id]) myViews[id]->Wait(wait);
958     }
959   }
960   else {
961     for(int i=0 ; i<MAXVIEW ; i++)
962       if (myViews[i])  myViews[i]->Wait(wait);
963   }
964
965   Standard_Boolean again = Standard_True;
966   while (again) {
967
968     Event ev;
969     ev.type = 0;
970
971     GetNextEvent(ev);
972
973     switch (ev.type) {
974
975     case ButtonPress :
976       Standard_Integer iv;
977       for (iv = 0; iv < MAXVIEW; iv++) {
978         if (myViews[iv]) {
979           if (myViews[iv]->win == ev.window)
980             break;
981         }
982       }
983       if (wait || id == iv) {
984         if (iv < MAXVIEW) {
985           id = iv;
986           X = ev.x;
987           Y = ev.y;
988           Button = ev.button;
989         }
990         else {
991           id = -1;
992         }
993         again = Standard_False;
994       }
995       break;
996
997     case MotionNotify :
998       if (wait) break;
999       X = ev.x;
1000       Y = ev.y;
1001       Button = 0;
1002       again = Standard_False;
1003       break;
1004     }
1005   }
1006
1007   if (id != -1) {
1008     X =  X - myViews[id]->GetDx();
1009     Y = -Y - myViews[id]->GetDy();
1010   }
1011   if (!wait) myViews[id]->Wait(!wait);
1012 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1013   Standard_Integer aWindowNumber;
1014
1015   id = MAXVIEW;
1016   while (id >= MAXVIEW)
1017   {
1018     GetNextEvent(wait, aWindowNumber, X, Y, Button);
1019
1020     if (Y < 0)
1021     {
1022       continue; // mouse clicked on window title
1023     }
1024
1025     for (Standard_Integer anIter = 0; anIter < MAXVIEW; anIter++)
1026     {
1027       if (myViews[anIter] && myViews[anIter]->IsEqualWindows (aWindowNumber))
1028       {
1029         id = anIter;
1030       }
1031     }
1032   }
1033
1034   X =  X - myViews[id]->GetDx();
1035   Y = -Y - myViews[id]->GetDy();
1036
1037 #else
1038   HANDLE hWnd;
1039
1040   id = MAXVIEW; //:abv 29.05.02: cycle for working in console mode
1041   while ( id >= MAXVIEW ) {
1042     if (wait)
1043       Draw_Window::SelectWait(hWnd, X, Y, Button);
1044     else
1045       Draw_Window::SelectNoWait(hWnd, X, Y, Button);
1046
1047     // Recherche du numero de la vue grace au HANDLE
1048     for(int i=0 ; i<MAXVIEW ; i++)
1049       if (myViews[i] && myViews[i]->win == hWnd )  id = i;
1050   }
1051   X =  X - myViews[id]->GetDx();
1052   Y = -Y - myViews[id]->GetDy();
1053 #endif
1054 }
1055
1056 //=======================================================================
1057 //function : Pick
1058 //purpose  :
1059 //=======================================================================
1060
1061 Standard_Integer Draw_Viewer::Pick(const Standard_Integer id,
1062                           const Standard_Integer X, const Standard_Integer Y, const Standard_Integer Prec,
1063                           Handle(Draw_Drawable3D)& D,
1064                           const Standard_Integer first) const
1065 {
1066   if (Draw_Batch) return 0;
1067   if (myViews[id] == NULL)
1068     return 0;
1069
1070   // is this the only view in its category
1071   Standard_Boolean is2d = myViews[id]->Is2D();
1072   Standard_Integer i,nbviews = 0;
1073   for (i = 0; i < MAXVIEW; i++)
1074   {
1075     if (myViews[i])
1076       if (myViews[i]->Is2D() == is2d)
1077         ++nbviews;
1078   }
1079   Standard_Boolean only = (nbviews == 1);
1080
1081   CurrentMode = PICK;
1082   xpick = X;
1083   ypick = Y;
1084   precpick = Prec;
1085   found = Standard_False;
1086   Standard_Real x1,x2,y1,y2;
1087   for (i = first+1; i <= myDrawables.Length(); i++) {
1088     Standard_Boolean reject = Standard_False;
1089     // rejection if only view
1090     if (only) {
1091       myDrawables(i)->Bounds(x1,x2,y1,y2);
1092       if ((xpick+Prec < x1) || (xpick-Prec > x2) ||
1093           (ypick+Prec < y1) || (ypick-Prec > y2))
1094         reject = Standard_True;
1095     }
1096     if (!reject) {
1097       DrawOnView(id,myDrawables(i));
1098       if (found)
1099         break;
1100     }
1101   }
1102   CurrentMode = DRAW;
1103   found = Standard_False;
1104   if (i <= myDrawables.Length())
1105     D = myDrawables(i);
1106   else
1107     i = 0;
1108   return i;
1109 }
1110
1111 //=======================================================================
1112 //function : LastPick
1113 //purpose  :
1114 //=======================================================================
1115
1116 void Draw_Viewer::LastPick(gp_Pnt& P1, gp_Pnt& P2, Standard_Real& Param)
1117 {
1118   if (Draw_Batch) return;
1119   P1    = lastPickP1;
1120   P2    = lastPickP2;
1121   Param = lastPickParam;
1122 }
1123
1124 //=======================================================================
1125 //function : ~Draw_Viewer
1126 //purpose  :
1127 //=======================================================================
1128
1129 Draw_Viewer::~Draw_Viewer()
1130 {
1131   if (Draw_Batch) return;
1132   for (Standard_Integer id = 0; id < MAXVIEW; id++)
1133     DeleteView(id);
1134 }
1135
1136 //=======================================================================
1137 //function : operator<<
1138 //purpose  :
1139 //=======================================================================
1140
1141 Draw_Viewer& Draw_Viewer::operator<<(const Handle(Draw_Drawable3D)& d3d)
1142 {
1143   if (Draw_Batch) return *this;
1144   if (!d3d.IsNull()) {
1145     AddDrawable(d3d);
1146     for (Standard_Integer id = 0; id < MAXVIEW; id++)
1147       DrawOnView(id,d3d);
1148   }
1149   return *this;
1150 }
1151
1152 //=======================================================================
1153 //function : GetDrawables
1154 //purpose  :
1155 //=======================================================================
1156 const Draw_SequenceOfDrawable3D& Draw_Viewer::GetDrawables()
1157 {
1158   return myDrawables;
1159 }
1160
1161 // *******************************************************************
1162 // DISPLAY methods
1163 // *******************************************************************
1164
1165
1166 void Draw_Flush()
1167 {
1168   if (Draw_Batch) return;
1169   if (highlight) curview->SetColor(highlightcol.ID());
1170   curview->DrawSegments(segm,nbseg);
1171   nbseg = 0;
1172 }
1173
1174 //=======================================================================
1175 //function : SetColor
1176 //purpose  :
1177 //=======================================================================
1178
1179 void Draw_Display::SetColor (const Draw_Color& col) const
1180 {
1181   if (Draw_Batch) return;
1182   if (col.ID() == currentcolor.ID()) return;
1183
1184   currentcolor = col;
1185   switch (CurrentMode) {
1186
1187   case DRAW :
1188     Draw_Flush();
1189     curview->SetColor(col.ID());
1190     break;
1191
1192   case POSTSCRIPT :
1193     (*ps_stream) << "stroke\nnewpath\n";
1194     (*ps_stream) << ps_width[col.ID()]<<" setlinewidth\n";
1195     (*ps_stream) << ps_gray[col.ID()]<<" setgray\n";
1196
1197   case PICK :
1198     break;
1199   }
1200 }
1201
1202 //=======================================================================
1203 //function : SetMode
1204 //purpose  :
1205 //=======================================================================
1206
1207 void Draw_Display::SetMode (const Standard_Integer M) const
1208 {
1209   if (Draw_Batch) return;
1210   switch (CurrentMode) {
1211
1212   case DRAW :
1213     Draw_Flush();
1214     curview->SetMode(M);
1215     break;
1216
1217   case PICK :
1218   case POSTSCRIPT :
1219     break;
1220   }
1221 }
1222
1223 //=======================================================================
1224 //function : Zoom
1225 //purpose  :
1226 //=======================================================================
1227
1228 Standard_Real Draw_Display::Zoom() const
1229 {
1230   if (Draw_Batch) return 1.;
1231   return curview->GetZoom();
1232 }
1233
1234 //=======================================================================
1235 //function : Flush
1236 //purpose  :
1237 //=======================================================================
1238
1239 void Draw_Display::Flush () const
1240 {
1241   if (Draw_Batch) return;
1242   Draw_Flush();
1243 }
1244
1245 //=======================================================================
1246 //function : DrawString
1247 //purpose  :
1248 //=======================================================================
1249
1250 void Draw_Display::DrawString(const gp_Pnt2d& ppt,
1251                               const Standard_CString S,
1252                               const Standard_Real moveX,
1253                               const Standard_Real moveY)
1254 {
1255   if (Draw_Batch) return;
1256   if (ppt.X() > 1.e09 || ppt.X() < -1.e09 ) return;
1257   if (ppt.Y() > 1.e09 || ppt.Y() < -1.e09 ) return;
1258
1259   gp_Pnt2d pt(ppt.X()*curview->GetZoom(),ppt.Y()*curview->GetZoom());
1260
1261   if (pt.X() > 1.e09 || pt.X() < -1.e09 ) return;
1262   if (pt.Y() > 1.e09 || pt.Y() < -1.e09 ) return;
1263
1264   switch (CurrentMode) {
1265
1266   case DRAW :
1267     {
1268       int X =   (int) ( pt.X() + moveX + curview->GetDx());
1269       int Y =   (int) (-pt.Y() + moveY - curview->GetDy());
1270       curview->DrawString(X,Y,(char *)S);
1271       if (Draw_Bounds) {
1272         if (pt.X() + moveX > xmax) xmax = pt.X();
1273         if (pt.X() + moveX < xmin) xmin = pt.X();
1274         if (-pt.Y() - moveY > ymax) ymax = -pt.Y();
1275         if (-pt.Y() - moveY < ymin) ymin = -pt.Y();
1276       }
1277     }
1278     break;
1279
1280   case POSTSCRIPT :
1281     {
1282       Standard_Integer x = (Standard_Integer )( (pt.X() + moveX - ps_vx) * ps_kx + ps_px);
1283       Standard_Integer y = (Standard_Integer )( (pt.Y() + moveY - ps_vy) * ps_ky + ps_py);
1284       (*ps_stream) <<"stroke\n";
1285       (*ps_stream) << x << " " << y << " m\n";
1286       (*ps_stream) <<"("<<S<<") show\nnewpath\n";
1287     }
1288     break;
1289
1290   case PICK :
1291     break;
1292   }
1293 }
1294
1295 //=======================================================================
1296 //function : DrawString
1297 //purpose  :
1298 //=======================================================================
1299
1300 void Draw_Display::DrawString(const gp_Pnt2d& ppt,
1301                               const Standard_CString S)
1302 {
1303   if (Draw_Batch) return;
1304   DrawString(ppt,S,0.0,0.0);
1305 }
1306
1307 //=======================================================================
1308 //function : DrawString
1309 //purpose  :
1310 //=======================================================================
1311
1312 void Draw_Display::DrawString(const gp_Pnt& pt,
1313                               const Standard_CString S,
1314                               const Standard_Real moveX,
1315                               const Standard_Real moveY)
1316 {
1317   if (Draw_Batch) return;
1318   DrawString(Project(pt),S,moveX,moveY);
1319 }
1320
1321 //=======================================================================
1322 //function : DrawString
1323 //purpose  :
1324 //=======================================================================
1325
1326 void Draw_Display::DrawString(const gp_Pnt& pt,
1327                               const Standard_CString S)
1328 {
1329   if (Draw_Batch) return;
1330   DrawString(Project(pt),S,0.0,0.0);
1331 }
1332
1333
1334 // *******************************************************************
1335 // Drawing data static variables
1336 // *******************************************************************
1337 static gp_Pnt2d PtCur;  // current 2D point
1338 static gp_Pnt PtPers;   // current 3D point for Pers
1339
1340 //=======================================================================
1341 //function : Project
1342 //purpose  :
1343 //=======================================================================
1344
1345 void Draw_Display::Project(const gp_Pnt& p, gp_Pnt2d& p2d) const
1346 {
1347   if (Draw_Batch) return;
1348   gp_Pnt pt = p;
1349   pt.Transform(curview->GetMatrix());
1350   Standard_Real xp,yp,zp;
1351   pt.Coord(xp,yp,zp);
1352   if (curview->IsPerspective()) {
1353     const Standard_Real aDistance = curview->GetFocalDistance();
1354     xp = xp * aDistance / (aDistance-zp);
1355     yp = yp * aDistance / (aDistance-zp);
1356   }
1357   p2d.SetCoord(xp,yp);
1358 }
1359
1360 //=======================================================================
1361 //function : Draw_Display
1362 //purpose  :
1363 //=======================================================================
1364
1365 Draw_Display::Draw_Display ()
1366 {
1367   if (Draw_Batch) return;
1368   if (curview) {
1369     PtPers.SetCoord(0., 0., 0.);
1370     PtPers.Transform(curview->GetMatrix());
1371     PtCur.SetCoord(PtPers.X()*curview->GetZoom(),PtPers.Y()*curview->GetZoom());
1372   }
1373 }
1374
1375 //=======================================================================
1376 //function : MoveTo 2D
1377 //purpose  :
1378 //=======================================================================
1379
1380 void Draw_Display::MoveTo (const gp_Pnt2d& pp)
1381 {
1382   if (Draw_Batch) return;
1383   const Standard_Real aZoom = curview->GetZoom();
1384   gp_Pnt2d pt(pp.X() * aZoom, pp.Y() * aZoom);
1385   switch (CurrentMode) {
1386
1387   case DRAW :
1388     PtCur = pt;
1389     if (Draw_Bounds) {
1390       if (pt.X() > xmax) xmax = pt.X();
1391       if (pt.X() < xmin) xmin = pt.X();
1392       if (pt.Y() > ymax) ymax = pt.Y();
1393       if (pt.Y() < ymin) ymin = pt.Y();
1394     }
1395     break;
1396
1397   case PICK :
1398     PtCur = pt;
1399     break;
1400
1401   case POSTSCRIPT :
1402     {
1403       Standard_Integer x = (Standard_Integer )( (pt.X() - ps_vx) * ps_kx + ps_px);
1404       Standard_Integer y = (Standard_Integer )( (pt.Y() - ps_vy) * ps_ky + ps_py);
1405       (*ps_stream) <<"stroke\nnewpath\n"<< x << " " << y << " m\n";
1406     }
1407     break;
1408   }
1409 }
1410
1411 //=======================================================================
1412 //function : DrawTo 2D
1413 //purpose  :
1414 //=======================================================================
1415 inline  Standard_Integer CalculRegion(const Standard_Real x,
1416                                       const Standard_Real y,
1417                                       const Standard_Real x1,
1418                                       const Standard_Real y1,
1419                                       const Standard_Real x2,
1420                                       const Standard_Real y2) {
1421   Standard_Integer r;
1422   if(x<x1) { r=1; }  else { if(x>x2) { r=2; } else { r=0; } }
1423   if(y<y1) { r|=4; } else { if(y>y2) { r|=8; } }
1424   return(r);
1425 }
1426
1427 Standard_Boolean Trim(gp_Pnt2d& P1,gp_Pnt2d& P2,
1428                       Standard_Real x0,
1429                       Standard_Real y0,
1430                       Standard_Real x1,
1431                       Standard_Real y1) {
1432   Standard_Real xa=P1.X(),ya=P1.Y(),xb=P2.X(),yb=P2.Y();
1433
1434   Standard_Integer regiona=0,regionb=0;
1435   regiona = CalculRegion(xa,ya,x0,y0,x1,y1);
1436   regionb = CalculRegion(xb,yb,x0,y0,x1,y1);
1437   if((regiona & regionb)==0) {
1438     Standard_Real dx=xb-xa;
1439     Standard_Real dy=yb-ya;
1440     Standard_Real dab=sqrt(dx*dx+dy*dy);
1441     if(dab<1e-10) return(Standard_False);
1442     dx/=dab;
1443     dy/=dab;
1444
1445     Standard_Real xm,ym,mfenx,mfeny;
1446     mfenx=xm=0.5*(x0+x1);
1447     mfeny=ym=0.5*(y0+y1);
1448     x1-=x0;     y1-=y0;
1449     Standard_Real d=sqrt(x1*x1+y1*y1) * 2;
1450
1451     Standard_Real p=(xm-xa)*dx+(ym-ya)*dy;
1452     xm=xa+p*dx;
1453     ym=ya+p*dy;
1454     gp_Pnt2d Pm(xm,ym);
1455
1456     gp_Pnt2d MFen(mfenx,mfeny);
1457     if(MFen.SquareDistance(Pm) > d*d) return(Standard_False);
1458
1459     Standard_Real PmDistP1 = Pm.Distance(P1);
1460     Standard_Real PmDistP2 = Pm.Distance(P2);
1461
1462     Standard_Real amab = (xm-xa)*(xb-xa)+(ym-ya)*(yb-ya);
1463
1464     if(amab > 0) { //-- M est compris entre A et B
1465       if(PmDistP1 > d) {
1466         P1.SetCoord(xm-d*dx,ym-d*dy);
1467       }
1468       if(PmDistP2 >d) {
1469         P2.SetCoord(xm+d*dx,ym+d*dy);
1470       }
1471     }
1472     else if(PmDistP1 < PmDistP2) {  //-- On a     M    P1 P2
1473       if(PmDistP2 > d) {
1474         P2.SetCoord(xm+d*dx,ym+d*dy);
1475       }
1476     }
1477     else { //-- On a      P1 P2 M
1478       if(PmDistP1 > d) {
1479         P1.SetCoord(xm-d*dx,ym-d*dy);
1480       }
1481     }
1482     return(Standard_True);
1483   }
1484   else return(Standard_False);
1485 }
1486
1487
1488
1489
1490 void Draw_Display::DrawTo (const gp_Pnt2d& pp2)
1491 {
1492   if (Draw_Batch) return;
1493   if (pp2.X() > 1.e09 || pp2.X() < -1.e09 ) return;
1494   if (pp2.Y() > 1.e09 || pp2.Y() < -1.e09 ) return;
1495
1496   gp_Pnt2d p2(pp2.X() * curview->GetZoom(), pp2.Y() * curview->GetZoom());
1497
1498   if (p2.X() > 1.e09 || p2.X() < -1.e09 ) return;
1499   if (p2.Y() > 1.e09 || p2.Y() < -1.e09 ) return;
1500
1501   gp_Pnt2d p1 = PtCur;
1502   if (p1.X() > 1.e09 || p1.X() < -1.e09 ) return;
1503   if (p1.Y() > 1.e09 || p1.Y() < -1.e09 ) return;
1504
1505   PtCur = p2;
1506
1507   switch (CurrentMode) {
1508
1509   case DRAW : {
1510
1511 #if 1
1512     Standard_Integer x0,y0,x1,y1;
1513     curview->GetFrame(x0,y0,x1,y1);
1514
1515
1516     //Standard_Integer qx0,qy0,qx1,qy1;
1517     //curview->viewer->GetFrame(curview->id,qx0,qy0,qx1,qy1);
1518     //if(qx0!=x0 || qx1!=x1 || qy0!=y0 || qy1!=y1) {
1519     //  x0=qx0; x1=qx1; y0=qy0; y1=qy1;
1520     //}
1521
1522
1523
1524     gp_Pnt2d PI1(p1);
1525     gp_Pnt2d PI2(p2);
1526
1527     if(Trim(PI1,PI2,x0,y0,x1,y1))
1528     {
1529       segm[nbseg].Init(static_cast<Standard_Integer>( PI1.X() + curview->GetDx()),
1530                        static_cast<Standard_Integer>(-PI1.Y() - curview->GetDy()),
1531                        static_cast<Standard_Integer>( PI2.X() + curview->GetDx()),
1532                        static_cast<Standard_Integer>(-PI2.Y() - curview->GetDy()));
1533       ++nbseg;
1534     }
1535 #else
1536     segm[nbseg].Init(static_cast<Standard_Integer>( p1.X() + curview->GetDx()),
1537                      static_cast<Standard_Integer>(-p1.Y() - curview->GetDy()),
1538                      static_cast<Standard_Integer>( p2.X() + curview->GetDx()),
1539                      static_cast<Standard_Integer>(-p2.Y() - curview->GetDy()));
1540     nbseg++;
1541 #endif
1542     if (nbseg == MAXSEGMENT) {
1543       Draw_Flush();
1544     }
1545     if (Draw_Bounds) {
1546       if (p2.X() > xmax) xmax = p2.X();
1547       if (p2.X() < xmin) xmin = p2.X();
1548       if (p2.Y() > ymax) ymax = p2.Y();
1549       if (p2.Y() < ymin) ymin = p2.Y();
1550     }
1551   }
1552     break;
1553
1554   case PICK :
1555     if (!found) {
1556       Standard_Integer x1 =  (int) p1.X() ;
1557       Standard_Integer y1 =  (int) p1.Y() ;
1558       Standard_Integer x2 =  (int) p2.X() ;
1559       Standard_Integer y2 =  (int) p2.Y() ;
1560       if ((x1 >= xpick + precpick) && (x2 >= xpick + precpick)) break;
1561       if ((x1 <= xpick - precpick) && (x2 <= xpick - precpick)) break;
1562       if ((y1 >= ypick + precpick) && (y2 >= ypick + precpick)) break;
1563       if ((y1 <= ypick - precpick) && (y2 <= ypick - precpick)) break;
1564
1565       Standard_Boolean inside = Standard_True;
1566       if ((x1 > xpick + precpick) || (x2 > xpick + precpick)) {
1567         Standard_Real y = (Standard_Real) y1 +
1568           (Standard_Real) (y2-y1) * (Standard_Real) (xpick+precpick-x1) /
1569             (Standard_Real) (x2 - x1);
1570         if ( (y < ypick+precpick) && (y > ypick - precpick)) {
1571           found = Standard_True;
1572           lastPickParam = (Standard_Real) (xpick - x1) /
1573             (Standard_Real) (x2 - x1);
1574           break;
1575         }
1576         else
1577           inside = Standard_False;
1578       }
1579
1580       if ((x1 < xpick - precpick) || (x2 < xpick - precpick)) {
1581         Standard_Real y = (Standard_Real) y1 +
1582           (Standard_Real) (y2-y1) * (Standard_Real) (xpick-precpick-x1) /
1583             (Standard_Real) (x2 - x1);
1584         if ( (y < ypick+precpick) && (y > ypick - precpick)) {
1585           found = Standard_True;
1586           lastPickParam = (Standard_Real) (xpick - x1) /
1587             (Standard_Real) (x2 - x1);
1588           break;
1589         }
1590         else
1591           inside = Standard_False;
1592       }
1593
1594
1595       if ((y1 > ypick + precpick) || (y2 > ypick + precpick)) {
1596         Standard_Real x = (Standard_Real) x1 +
1597           (Standard_Real) (x2-x1) * (Standard_Real) (ypick+precpick-y1) /
1598             (Standard_Real) (y2 - y1);
1599         if ( (x < xpick+precpick) && (x > xpick - precpick)) {
1600           found = Standard_True;
1601           lastPickParam = (Standard_Real) (ypick - y1) /
1602             (Standard_Real) (y2 - y1);
1603           break;
1604         }
1605         else
1606           inside = Standard_False;
1607       }
1608
1609
1610       if ((y1 < ypick - precpick) || (y2 < ypick - precpick)) {
1611         Standard_Real x = (Standard_Real) x1 +
1612           (Standard_Real) (x2-x1) * (Standard_Real) (ypick-precpick-y1) /
1613             (Standard_Real) (y2 - y1);
1614         if ( (x < xpick+precpick) && (x > xpick - precpick)) {
1615           found = Standard_True;
1616           lastPickParam = (Standard_Real) (ypick - y1) /
1617             (Standard_Real) (y2 - y1);
1618           break;
1619         }
1620         else
1621           inside = Standard_False;
1622       }
1623     found = found || inside;
1624       if (found) {
1625         if (Abs(x2-x1) > Abs(y2-y1)) {
1626           if (Abs(x2-x1) < 1e-5)  lastPickParam = 0;
1627           else
1628             lastPickParam = (Standard_Real)(xpick - x1) /
1629               (Standard_Real)(x2 - x1);
1630         }
1631         else {
1632           if (Abs(y2-y1) < 1e-5)  lastPickParam = 0;
1633           else
1634             lastPickParam = (Standard_Real)(ypick - y1) /
1635               (Standard_Real)(y2 - y1);
1636         }
1637       }
1638     }
1639     break;
1640
1641   case POSTSCRIPT :
1642     {
1643       Standard_Integer x = (Standard_Integer )( (p2.X() - ps_vx) * ps_kx + ps_px);
1644       Standard_Integer y = (Standard_Integer )( (p2.Y() - ps_vy) * ps_ky + ps_py);
1645       (*ps_stream) << x << " " << y << " l\n";
1646     }
1647     break;
1648   }
1649
1650 }
1651
1652 //=======================================================================
1653 //function : MoveTo
1654 //purpose  :
1655 //=======================================================================
1656
1657 void Draw_Display::MoveTo (const gp_Pnt& pt)
1658 {
1659   if (Draw_Batch) return;
1660   if (CurrentMode == PICK) {
1661     if (!found) lastPickP1 = pt;
1662     else return;
1663   }
1664   PtPers = pt;
1665   PtPers.Transform(curview->GetMatrix());
1666   Standard_Real xp = PtPers.X();
1667   Standard_Real yp = PtPers.Y();
1668   if (curview->IsPerspective())
1669   {
1670     Standard_Real ZPers = PtPers.Z();
1671     const Standard_Real aDistance = curview->GetFocalDistance();
1672     if (ZPers < aDistance * precpers)
1673     {
1674       xp=xp * aDistance / (aDistance-ZPers);
1675       yp=yp * aDistance / (aDistance-ZPers);
1676     }
1677   }
1678   MoveTo(gp_Pnt2d(xp,yp));
1679 }
1680
1681 //=======================================================================
1682 //function : DrawTo
1683 //purpose  :
1684 //=======================================================================
1685
1686 void Draw_Display::DrawTo (const gp_Pnt& pt)
1687 {
1688   if (Draw_Batch) return;
1689   if ((CurrentMode == PICK) && found) return;
1690
1691   gp_Pnt pt2 = pt.Transformed(curview->GetMatrix());
1692   Standard_Real xp2 = pt2.X();
1693   Standard_Real yp2 = pt2.Y();
1694
1695   if (curview->IsPerspective())
1696   {
1697     const Standard_Real aZoom     = curview->GetZoom();
1698     const Standard_Real aDistance = curview->GetFocalDistance();
1699
1700     Standard_Real xp1 = PtPers.X();
1701     Standard_Real yp1 = PtPers.Y();
1702     Standard_Real zp1 = PtPers.Z();
1703     Standard_Real zp2 = pt2.Z();
1704     PtPers   = pt2;
1705     if ((zp1 >= aDistance*precpers) && (zp2 >= aDistance*precpers) )
1706     {
1707       return;  // segment is not visible in perspective (behind the eye)
1708     }
1709     else if (zp1 >= aDistance*precpers)
1710     {
1711       xp1=xp1+(xp2-xp1)*(aDistance*precpers-zp1)/(zp2-zp1);
1712       yp1=yp1+(yp2-yp1)*(aDistance*precpers-zp1)/(zp2-zp1);
1713       zp1=aDistance*precpers;
1714       xp1=xp1*aDistance/(aDistance-zp1);
1715       yp1=yp1*aDistance/(aDistance-zp1);
1716       MoveTo( gp_Pnt2d(xp1 * aZoom, yp1 * aZoom) );
1717     }
1718     else if (zp2 >= aDistance*precpers)
1719     {
1720       xp2=xp2+(xp1-xp2)*(aDistance*precpers-zp2)/(zp1-zp2);
1721       yp2=yp2+(yp1-yp2)*(aDistance*precpers-zp2)/(zp1-zp2);
1722       zp2=aDistance*precpers;
1723     }
1724     xp2 = xp2 * aDistance / (aDistance - zp2);
1725     yp2 = yp2 * aDistance / (aDistance - zp2);
1726   }
1727   DrawTo(gp_Pnt2d(xp2,yp2));
1728   if (CurrentMode == PICK) {
1729     if      (!found)    lastPickP1 = pt;
1730     else                lastPickP2 = pt;
1731   }
1732 }
1733
1734 //=======================================================================
1735 //function : Draw
1736 //purpose  :
1737 //=======================================================================
1738
1739 void Draw_Display::Draw (const gp_Pnt& p1, const gp_Pnt& p2)
1740 {
1741   if (Draw_Batch) return;
1742   MoveTo(p1);
1743   DrawTo(p2);
1744 }
1745
1746 //=======================================================================
1747 //function : Draw
1748 //purpose  :
1749 //=======================================================================
1750
1751 void Draw_Display::Draw(const gp_Pnt2d& p1, const gp_Pnt2d& p2)
1752 {
1753   if (Draw_Batch) return;
1754   MoveTo(p1);
1755   DrawTo(p2);
1756 }
1757
1758
1759 //=======================================================================
1760 //function : ViewId
1761 //purpose  :
1762 //=======================================================================
1763
1764 Standard_Integer Draw_Display::ViewId() const
1765 {
1766   if (Draw_Batch) return 0;
1767   return curviewId;
1768 }
1769
1770
1771 //=======================================================================
1772 //function : HasPicked
1773 //purpose  :
1774 //=======================================================================
1775
1776 Standard_Boolean Draw_Display::HasPicked() const
1777 {
1778   if (Draw_Batch) return Standard_False;
1779   return found;
1780 }
1781