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