ec9848f662e8ca713699e44f3a91b83bfe104aac
[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 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                                   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) return Standard_False;;
700   Flush();
701   if (myViews[id]) {
702     return myViews[id]->Save(filename);
703   }
704   else
705   {
706     std::cerr << "View " << id << " doesn't exists!\n";
707     return Standard_False;
708   }
709 }
710
711 //=======================================================================
712 //function : RepaintAll
713 //purpose  :
714 //=======================================================================
715
716 void Draw_Viewer::RepaintAll () const
717 {
718   if (Draw_Batch) return;
719   for (Standard_Integer id = 0; id < MAXVIEW; id++)
720     RepaintView(id);
721 }
722
723 //=======================================================================
724 //function : Repaint2D
725 //purpose  :
726 //=======================================================================
727
728 void Draw_Viewer::Repaint2D () const
729 {
730   if (Draw_Batch) return;
731   for (Standard_Integer id = 0; id < MAXVIEW; id++)
732     if (myViews[id]) {
733       if (myViews[id]->Is2D())
734         RepaintView(id);
735     }
736 }
737
738 //=======================================================================
739 //function : Repaint3D
740 //purpose  :
741 //=======================================================================
742
743 void Draw_Viewer::Repaint3D () const
744 {
745   if (Draw_Batch) return;
746   for (Standard_Integer id = 0; id < MAXVIEW; id++)
747     if (myViews[id]) {
748       if (!myViews[id]->Is2D())
749         RepaintView(id);
750     }
751 }
752
753 //=======================================================================
754 //function : DeleteView
755 //purpose  :
756 //=======================================================================
757
758 void Draw_Viewer::DeleteView(const Standard_Integer id)
759 {
760   if (Draw_Batch) return;
761   if (myViews[id] != NULL) {
762     delete myViews[id];
763     myViews[id] = NULL;
764   }
765 }
766
767 //=======================================================================
768 //function : Clear
769 //purpose  :
770 //=======================================================================
771
772 void Draw_Viewer::Clear()
773 {
774   if (Draw_Batch) return;
775   for (Standard_Integer i = 1; i <= myDrawables.Length(); i++)
776     myDrawables(i)->Visible(Standard_False);
777   myDrawables.Clear();
778   for (Standard_Integer id = 0; id < MAXVIEW; id++)
779     ClearView(id);
780 }
781
782 //=======================================================================
783 //function : Clear2D
784 //purpose  :
785 //=======================================================================
786
787 void Draw_Viewer::Clear2D()
788 {
789   if (Draw_Batch) return;
790   Standard_Integer i = 1;
791   while (i <= myDrawables.Length()) {
792     if (myDrawables(i)->Is3D())
793       i++;
794     else {
795       myDrawables(i)->Visible(Standard_False);
796       myDrawables.Remove(i);
797     }
798   }
799   for (Standard_Integer id = 0; id < MAXVIEW; id++) {
800     if (myViews[id]) {
801       if (myViews[id]->Is2D())
802         ClearView(id);
803     }
804   }
805 }
806
807 //=======================================================================
808 //function : Clear3D
809 //purpose  :
810 //=======================================================================
811
812 void Draw_Viewer::Clear3D()
813 {
814   if (Draw_Batch) return;
815   Standard_Integer i = 1;
816   while (i <= myDrawables.Length()) {
817     if (myDrawables(i)->Is3D()) {
818       myDrawables(i)->Visible(Standard_False);
819       myDrawables.Remove(i);
820     }
821     else
822       i++;
823   }
824   for (Standard_Integer id = 0; id < MAXVIEW; id++) {
825     if (myViews[id]) {
826       if (!myViews[id]->Is2D())
827         ClearView(id);
828     }
829   }
830 }
831
832 //=======================================================================
833 //function : Flush
834 //purpose  :
835 //=======================================================================
836
837 void Draw_Viewer::Flush()
838 {
839   if (Draw_Batch) return;
840   Draw_Window::Flush();
841 }
842
843 //=======================================================================
844 //function : DrawOnView
845 //purpose  :
846 //=======================================================================
847
848 void Draw_Viewer::DrawOnView(const Standard_Integer id,
849                              const Handle(Draw_Drawable3D)& D) const
850 {
851   if (Draw_Batch) return;
852   if (myViews[id]) {
853     Draw_Display d = MakeDisplay(id);
854     xmin = ymin = DRAWINFINITE;
855     xmax = ymax = -DRAWINFINITE;
856
857     Standard_Boolean view2d = myViews[id]->Is2D();
858     myViews[id]->ResetFrame();
859     if ((D->Is3D() && !view2d) || (!D->Is3D() && view2d))
860     {
861       D->DrawOn(d);
862       if (CurrentMode == DRAW)
863         D->SetBounds(xmin,xmax,ymin,ymax);
864       d.Flush();
865     }
866   }
867 }
868
869 //=======================================================================
870 //function : HighlightOnView
871 //purpose  :
872 //=======================================================================
873
874 void Draw_Viewer::HighlightOnView (const Standard_Integer id,
875                                    const Handle(Draw_Drawable3D)& D,
876                                    const Draw_ColorKind C) const
877 {
878   if (Draw_Batch) return;
879   highlight = Standard_True;
880   highlightcol = C;
881   DrawOnView(id,D);
882   highlight = Standard_False;
883 }
884
885 //=======================================================================
886 //function : AddDrawable
887 //purpose  :
888 //=======================================================================
889
890 void Draw_Viewer::AddDrawable (const Handle(Draw_Drawable3D)& D)
891 {
892   if (Draw_Batch) return;
893   if (!D.IsNull() && !D->Visible()) {
894     myDrawables.Append(D);
895     D->Visible(Standard_True);
896   }
897 }
898
899 //=======================================================================
900 //function : RemoveDrawable
901 //purpose  :
902 //=======================================================================
903
904 void Draw_Viewer::RemoveDrawable (const Handle(Draw_Drawable3D)& D)
905 {
906   if (Draw_Batch) return;
907   if (!D.IsNull() && D->Visible()) {
908     Standard_Integer index;
909     for (index = 1; index <= myDrawables.Length(); index++) {
910       if (myDrawables(index) == D) {
911         D->Visible(Standard_False);
912         myDrawables.Remove(index);
913         return;
914       }
915     }
916   }
917 }
918
919 //=======================================================================
920 //function : MakeDisplay
921 //purpose  : return a display on the view
922 //=======================================================================
923
924 Draw_Display Draw_Viewer::MakeDisplay (const Standard_Integer id) const
925 {
926   if (Draw_Batch) {Draw_Display dis;return dis;}
927   curviewId = id;
928   curview = myViews[id];
929   int GXcopy = 0x3;
930   nbseg = 0;
931   Draw_Color initcol(Draw_blanc);
932   // to force setting the color
933   currentcolor = Draw_Color(Draw_rouge);
934   Draw_Display dis;
935   dis.SetColor(initcol);
936   dis.SetMode(GXcopy);
937   return dis;
938 }
939
940 //=======================================================================
941 //function : Select
942 //purpose  :
943 //=======================================================================
944 void Draw_Viewer::Select (Standard_Integer& id, Standard_Integer& X, Standard_Integer& Y,
945                           Standard_Integer& Button, Standard_Boolean wait)
946 {
947   if (Draw_Batch) return;
948   Flush();
949 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
950   if (!wait) {
951     if (id >=0 && id < MAXVIEW) {
952       if (myViews[id]) myViews[id]->Wait(wait);
953     }
954   }
955   else {
956     for(int i=0 ; i<MAXVIEW ; i++)
957       if (myViews[i])  myViews[i]->Wait(wait);
958   }
959
960   Standard_Boolean again = Standard_True;
961   while (again) {
962
963     Event ev;
964     ev.type = 0;
965
966     GetNextEvent(ev);
967
968     switch (ev.type) {
969
970     case ButtonPress :
971       Standard_Integer iv;
972       for (iv = 0; iv < MAXVIEW; iv++) {
973         if (myViews[iv]) {
974           if (myViews[iv]->win == ev.window)
975             break;
976         }
977       }
978       if (wait || id == iv) {
979         if (iv < MAXVIEW) {
980           id = iv;
981           X = ev.x;
982           Y = ev.y;
983           Button = ev.button;
984         }
985         else {
986           id = -1;
987         }
988         again = Standard_False;
989       }
990       break;
991
992     case MotionNotify :
993       if (wait) break;
994       X = ev.x;
995       Y = ev.y;
996       Button = 0;
997       again = Standard_False;
998       break;
999     }
1000   }
1001
1002   if (id != -1) {
1003     X =  X - myViews[id]->GetDx();
1004     Y = -Y - myViews[id]->GetDy();
1005   }
1006   if (!wait) myViews[id]->Wait(!wait);
1007 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1008   Standard_Integer aWindowNumber;
1009
1010   id = MAXVIEW;
1011   while (id >= MAXVIEW)
1012   {
1013     GetNextEvent(wait, aWindowNumber, X, Y, Button);
1014
1015     if (Y < 0)
1016     {
1017       continue; // mouse clicked on window title
1018     }
1019
1020     for (Standard_Integer anIter = 0; anIter < MAXVIEW; anIter++)
1021     {
1022       if (myViews[anIter] && myViews[anIter]->IsEqualWindows (aWindowNumber))
1023       {
1024         id = anIter;
1025       }
1026     }
1027   }
1028
1029   X =  X - myViews[id]->GetDx();
1030   Y = -Y - myViews[id]->GetDy();
1031
1032 #else
1033   HANDLE hWnd;
1034
1035   id = MAXVIEW; //:abv 29.05.02: cycle for working in console mode
1036   while ( id >= MAXVIEW ) {
1037     if (wait)
1038       Draw_Window::SelectWait(hWnd, X, Y, Button);
1039     else
1040       Draw_Window::SelectNoWait(hWnd, X, Y, Button);
1041
1042     // Recherche du numero de la vue grace au HANDLE
1043     for(int i=0 ; i<MAXVIEW ; i++)
1044       if (myViews[i] && myViews[i]->win == hWnd )  id = i;
1045   }
1046   X =  X - myViews[id]->GetDx();
1047   Y = -Y - myViews[id]->GetDy();
1048 #endif
1049 }
1050
1051 //=======================================================================
1052 //function : Pick
1053 //purpose  :
1054 //=======================================================================
1055
1056 Standard_Integer Draw_Viewer::Pick(const Standard_Integer id,
1057                           const Standard_Integer X, const Standard_Integer Y, const Standard_Integer Prec,
1058                           Handle(Draw_Drawable3D)& D,
1059                           const Standard_Integer first) const
1060 {
1061   if (Draw_Batch) return 0;
1062   if (myViews[id] == NULL)
1063     return 0;
1064
1065   // is this the only view in its category
1066   Standard_Boolean is2d = myViews[id]->Is2D();
1067   Standard_Integer i,nbviews = 0;
1068   for (i = 0; i < MAXVIEW; i++)
1069   {
1070     if (myViews[i])
1071       if (myViews[i]->Is2D() == is2d)
1072         ++nbviews;
1073   }
1074   Standard_Boolean only = (nbviews == 1);
1075
1076   CurrentMode = PICK;
1077   xpick = X;
1078   ypick = Y;
1079   precpick = Prec;
1080   found = Standard_False;
1081   Standard_Real x1,x2,y1,y2;
1082   for (i = first+1; i <= myDrawables.Length(); i++) {
1083     Standard_Boolean reject = Standard_False;
1084     // rejection if only view
1085     if (only) {
1086       myDrawables(i)->Bounds(x1,x2,y1,y2);
1087       if ((xpick+Prec < x1) || (xpick-Prec > x2) ||
1088           (ypick+Prec < y1) || (ypick-Prec > y2))
1089         reject = Standard_True;
1090     }
1091     if (!reject) {
1092       DrawOnView(id,myDrawables(i));
1093       if (found)
1094         break;
1095     }
1096   }
1097   CurrentMode = DRAW;
1098   found = Standard_False;
1099   if (i <= myDrawables.Length())
1100     D = myDrawables(i);
1101   else
1102     i = 0;
1103   return i;
1104 }
1105
1106 //=======================================================================
1107 //function : LastPick
1108 //purpose  :
1109 //=======================================================================
1110
1111 void Draw_Viewer::LastPick(gp_Pnt& P1, gp_Pnt& P2, Standard_Real& Param)
1112 {
1113   if (Draw_Batch) return;
1114   P1    = lastPickP1;
1115   P2    = lastPickP2;
1116   Param = lastPickParam;
1117 }
1118
1119 //=======================================================================
1120 //function : ~Draw_Viewer
1121 //purpose  :
1122 //=======================================================================
1123
1124 Draw_Viewer::~Draw_Viewer()
1125 {
1126   if (Draw_Batch) return;
1127   for (Standard_Integer id = 0; id < MAXVIEW; id++)
1128     DeleteView(id);
1129 }
1130
1131 //=======================================================================
1132 //function : operator<<
1133 //purpose  :
1134 //=======================================================================
1135
1136 Draw_Viewer& Draw_Viewer::operator<<(const Handle(Draw_Drawable3D)& d3d)
1137 {
1138   if (Draw_Batch) return *this;
1139   if (!d3d.IsNull()) {
1140     AddDrawable(d3d);
1141     for (Standard_Integer id = 0; id < MAXVIEW; id++)
1142       DrawOnView(id,d3d);
1143   }
1144   return *this;
1145 }
1146
1147 //=======================================================================
1148 //function : GetDrawables
1149 //purpose  :
1150 //=======================================================================
1151 const Draw_SequenceOfDrawable3D& Draw_Viewer::GetDrawables()
1152 {
1153   return myDrawables;
1154 }
1155
1156 // *******************************************************************
1157 // DISPLAY methods
1158 // *******************************************************************
1159
1160
1161 void Draw_Flush()
1162 {
1163   if (Draw_Batch) return;
1164   if (highlight) curview->SetColor(highlightcol.ID());
1165   curview->DrawSegments(segm,nbseg);
1166   nbseg = 0;
1167 }
1168
1169 //=======================================================================
1170 //function : SetColor
1171 //purpose  :
1172 //=======================================================================
1173
1174 void Draw_Display::SetColor (const Draw_Color& col) const
1175 {
1176   if (Draw_Batch) return;
1177   if (col.ID() == currentcolor.ID()) return;
1178
1179   currentcolor = col;
1180   switch (CurrentMode) {
1181
1182   case DRAW :
1183     Draw_Flush();
1184     curview->SetColor(col.ID());
1185     break;
1186
1187   case POSTSCRIPT :
1188     (*ps_stream) << "stroke\nnewpath\n";
1189     (*ps_stream) << ps_width[col.ID()]<<" setlinewidth\n";
1190     (*ps_stream) << ps_gray[col.ID()]<<" setgray\n";
1191
1192   case PICK :
1193     break;
1194   }
1195 }
1196
1197 //=======================================================================
1198 //function : SetMode
1199 //purpose  :
1200 //=======================================================================
1201
1202 void Draw_Display::SetMode (const Standard_Integer M) const
1203 {
1204   if (Draw_Batch) return;
1205   switch (CurrentMode) {
1206
1207   case DRAW :
1208     Draw_Flush();
1209     curview->SetMode(M);
1210     break;
1211
1212   case PICK :
1213   case POSTSCRIPT :
1214     break;
1215   }
1216 }
1217
1218 //=======================================================================
1219 //function : Zoom
1220 //purpose  :
1221 //=======================================================================
1222
1223 Standard_Real Draw_Display::Zoom() const
1224 {
1225   if (Draw_Batch) return 1.;
1226   return curview->GetZoom();
1227 }
1228
1229 //=======================================================================
1230 //function : Flush
1231 //purpose  :
1232 //=======================================================================
1233
1234 void Draw_Display::Flush () const
1235 {
1236   if (Draw_Batch) return;
1237   Draw_Flush();
1238 }
1239
1240 //=======================================================================
1241 //function : DrawString
1242 //purpose  :
1243 //=======================================================================
1244
1245 void Draw_Display::DrawString(const gp_Pnt2d& ppt,
1246                               const Standard_CString S,
1247                               const Standard_Real moveX,
1248                               const Standard_Real moveY)
1249 {
1250   if (Draw_Batch) return;
1251   if (ppt.X() > 1.e09 || ppt.X() < -1.e09 ) return;
1252   if (ppt.Y() > 1.e09 || ppt.Y() < -1.e09 ) return;
1253
1254   gp_Pnt2d pt(ppt.X()*curview->GetZoom(),ppt.Y()*curview->GetZoom());
1255
1256   if (pt.X() > 1.e09 || pt.X() < -1.e09 ) return;
1257   if (pt.Y() > 1.e09 || pt.Y() < -1.e09 ) return;
1258
1259   switch (CurrentMode) {
1260
1261   case DRAW :
1262     {
1263       int X =   (int) ( pt.X() + moveX + curview->GetDx());
1264       int Y =   (int) (-pt.Y() + moveY - curview->GetDy());
1265       curview->DrawString(X,Y,(char *)S);
1266       if (Draw_Bounds) {
1267         if (pt.X() + moveX > xmax) xmax = pt.X();
1268         if (pt.X() + moveX < xmin) xmin = pt.X();
1269         if (-pt.Y() - moveY > ymax) ymax = -pt.Y();
1270         if (-pt.Y() - moveY < ymin) ymin = -pt.Y();
1271       }
1272     }
1273     break;
1274
1275   case POSTSCRIPT :
1276     {
1277       Standard_Integer x = (Standard_Integer )( (pt.X() + moveX - ps_vx) * ps_kx + ps_px);
1278       Standard_Integer y = (Standard_Integer )( (pt.Y() + moveY - ps_vy) * ps_ky + ps_py);
1279       (*ps_stream) <<"stroke\n";
1280       (*ps_stream) << x << " " << y << " m\n";
1281       (*ps_stream) <<"("<<S<<") show\nnewpath\n";
1282     }
1283     break;
1284
1285   case PICK :
1286     break;
1287   }
1288 }
1289
1290 //=======================================================================
1291 //function : DrawString
1292 //purpose  :
1293 //=======================================================================
1294
1295 void Draw_Display::DrawString(const gp_Pnt2d& ppt,
1296                               const Standard_CString S)
1297 {
1298   if (Draw_Batch) return;
1299   DrawString(ppt,S,0.0,0.0);
1300 }
1301
1302 //=======================================================================
1303 //function : DrawString
1304 //purpose  :
1305 //=======================================================================
1306
1307 void Draw_Display::DrawString(const gp_Pnt& pt,
1308                               const Standard_CString S,
1309                               const Standard_Real moveX,
1310                               const Standard_Real moveY)
1311 {
1312   if (Draw_Batch) return;
1313   DrawString(Project(pt),S,moveX,moveY);
1314 }
1315
1316 //=======================================================================
1317 //function : DrawString
1318 //purpose  :
1319 //=======================================================================
1320
1321 void Draw_Display::DrawString(const gp_Pnt& pt,
1322                               const Standard_CString S)
1323 {
1324   if (Draw_Batch) return;
1325   DrawString(Project(pt),S,0.0,0.0);
1326 }
1327
1328
1329 // *******************************************************************
1330 // Drawing data static variables
1331 // *******************************************************************
1332 static gp_Pnt2d PtCur;  // current 2D point
1333 static gp_Pnt PtPers;   // current 3D point for Pers
1334
1335 //=======================================================================
1336 //function : Project
1337 //purpose  :
1338 //=======================================================================
1339
1340 void Draw_Display::Project(const gp_Pnt& p, gp_Pnt2d& p2d) const
1341 {
1342   if (Draw_Batch) return;
1343   gp_Pnt pt = p;
1344   pt.Transform(curview->GetMatrix());
1345   Standard_Real xp,yp,zp;
1346   pt.Coord(xp,yp,zp);
1347   if (curview->IsPerspective()) {
1348     const Standard_Real aDistance = curview->GetFocalDistance();
1349     xp = xp * aDistance / (aDistance-zp);
1350     yp = yp * aDistance / (aDistance-zp);
1351   }
1352   p2d.SetCoord(xp,yp);
1353 }
1354
1355 //=======================================================================
1356 //function : Draw_Display
1357 //purpose  :
1358 //=======================================================================
1359
1360 Draw_Display::Draw_Display ()
1361 {
1362   if (Draw_Batch) return;
1363   if (curview) {
1364     PtPers.SetCoord(0., 0., 0.);
1365     PtPers.Transform(curview->GetMatrix());
1366     PtCur.SetCoord(PtPers.X()*curview->GetZoom(),PtPers.Y()*curview->GetZoom());
1367   }
1368 }
1369
1370 //=======================================================================
1371 //function : MoveTo 2D
1372 //purpose  :
1373 //=======================================================================
1374
1375 void Draw_Display::MoveTo (const gp_Pnt2d& pp)
1376 {
1377   if (Draw_Batch) return;
1378   const Standard_Real aZoom = curview->GetZoom();
1379   gp_Pnt2d pt(pp.X() * aZoom, pp.Y() * aZoom);
1380   switch (CurrentMode) {
1381
1382   case DRAW :
1383     PtCur = pt;
1384     if (Draw_Bounds) {
1385       if (pt.X() > xmax) xmax = pt.X();
1386       if (pt.X() < xmin) xmin = pt.X();
1387       if (pt.Y() > ymax) ymax = pt.Y();
1388       if (pt.Y() < ymin) ymin = pt.Y();
1389     }
1390     break;
1391
1392   case PICK :
1393     PtCur = pt;
1394     break;
1395
1396   case POSTSCRIPT :
1397     {
1398       Standard_Integer x = (Standard_Integer )( (pt.X() - ps_vx) * ps_kx + ps_px);
1399       Standard_Integer y = (Standard_Integer )( (pt.Y() - ps_vy) * ps_ky + ps_py);
1400       (*ps_stream) <<"stroke\nnewpath\n"<< x << " " << y << " m\n";
1401     }
1402     break;
1403   }
1404 }
1405
1406 //=======================================================================
1407 //function : DrawTo 2D
1408 //purpose  :
1409 //=======================================================================
1410 inline  Standard_Integer CalculRegion(const Standard_Real x,
1411                                       const Standard_Real y,
1412                                       const Standard_Real x1,
1413                                       const Standard_Real y1,
1414                                       const Standard_Real x2,
1415                                       const Standard_Real y2) {
1416   Standard_Integer r;
1417   if(x<x1) { r=1; }  else { if(x>x2) { r=2; } else { r=0; } }
1418   if(y<y1) { r|=4; } else { if(y>y2) { r|=8; } }
1419   return(r);
1420 }
1421
1422 Standard_Boolean Trim(gp_Pnt2d& P1,gp_Pnt2d& P2,
1423                       Standard_Real x0,
1424                       Standard_Real y0,
1425                       Standard_Real x1,
1426                       Standard_Real y1) {
1427   Standard_Real xa=P1.X(),ya=P1.Y(),xb=P2.X(),yb=P2.Y();
1428
1429   Standard_Integer regiona=0,regionb=0;
1430   regiona = CalculRegion(xa,ya,x0,y0,x1,y1);
1431   regionb = CalculRegion(xb,yb,x0,y0,x1,y1);
1432   if((regiona & regionb)==0) {
1433     Standard_Real dx=xb-xa;
1434     Standard_Real dy=yb-ya;
1435     Standard_Real dab=sqrt(dx*dx+dy*dy);
1436     if(dab<1e-10) return(Standard_False);
1437     dx/=dab;
1438     dy/=dab;
1439
1440     Standard_Real xm,ym,mfenx,mfeny;
1441     mfenx=xm=0.5*(x0+x1);
1442     mfeny=ym=0.5*(y0+y1);
1443     x1-=x0;     y1-=y0;
1444     Standard_Real d=sqrt(x1*x1+y1*y1) * 2;
1445
1446     Standard_Real p=(xm-xa)*dx+(ym-ya)*dy;
1447     xm=xa+p*dx;
1448     ym=ya+p*dy;
1449     gp_Pnt2d Pm(xm,ym);
1450
1451     gp_Pnt2d MFen(mfenx,mfeny);
1452     if(MFen.SquareDistance(Pm) > d*d) return(Standard_False);
1453
1454     Standard_Real PmDistP1 = Pm.Distance(P1);
1455     Standard_Real PmDistP2 = Pm.Distance(P2);
1456
1457     Standard_Real amab = (xm-xa)*(xb-xa)+(ym-ya)*(yb-ya);
1458
1459     if(amab > 0) { //-- M est compris entre A et B
1460       if(PmDistP1 > d) {
1461         P1.SetCoord(xm-d*dx,ym-d*dy);
1462       }
1463       if(PmDistP2 >d) {
1464         P2.SetCoord(xm+d*dx,ym+d*dy);
1465       }
1466     }
1467     else if(PmDistP1 < PmDistP2) {  //-- On a     M    P1 P2
1468       if(PmDistP2 > d) {
1469         P2.SetCoord(xm+d*dx,ym+d*dy);
1470       }
1471     }
1472     else { //-- On a      P1 P2 M
1473       if(PmDistP1 > d) {
1474         P1.SetCoord(xm-d*dx,ym-d*dy);
1475       }
1476     }
1477     return(Standard_True);
1478   }
1479   else return(Standard_False);
1480 }
1481
1482
1483
1484
1485 void Draw_Display::DrawTo (const gp_Pnt2d& pp2)
1486 {
1487   if (Draw_Batch) return;
1488   if (pp2.X() > 1.e09 || pp2.X() < -1.e09 ) return;
1489   if (pp2.Y() > 1.e09 || pp2.Y() < -1.e09 ) return;
1490
1491   gp_Pnt2d p2(pp2.X() * curview->GetZoom(), pp2.Y() * curview->GetZoom());
1492
1493   if (p2.X() > 1.e09 || p2.X() < -1.e09 ) return;
1494   if (p2.Y() > 1.e09 || p2.Y() < -1.e09 ) return;
1495
1496   gp_Pnt2d p1 = PtCur;
1497   if (p1.X() > 1.e09 || p1.X() < -1.e09 ) return;
1498   if (p1.Y() > 1.e09 || p1.Y() < -1.e09 ) return;
1499
1500   PtCur = p2;
1501
1502   switch (CurrentMode) {
1503
1504   case DRAW : {
1505
1506 #if 1
1507     Standard_Integer x0,y0,x1,y1;
1508     curview->GetFrame(x0,y0,x1,y1);
1509
1510
1511     //Standard_Integer qx0,qy0,qx1,qy1;
1512     //curview->viewer->GetFrame(curview->id,qx0,qy0,qx1,qy1);
1513     //if(qx0!=x0 || qx1!=x1 || qy0!=y0 || qy1!=y1) {
1514     //  x0=qx0; x1=qx1; y0=qy0; y1=qy1;
1515     //}
1516
1517
1518
1519     gp_Pnt2d PI1(p1);
1520     gp_Pnt2d PI2(p2);
1521
1522     if(Trim(PI1,PI2,x0,y0,x1,y1))
1523     {
1524       segm[nbseg].Init(static_cast<Standard_Integer>( PI1.X() + curview->GetDx()),
1525                        static_cast<Standard_Integer>(-PI1.Y() - curview->GetDy()),
1526                        static_cast<Standard_Integer>( PI2.X() + curview->GetDx()),
1527                        static_cast<Standard_Integer>(-PI2.Y() - curview->GetDy()));
1528       ++nbseg;
1529     }
1530 #else
1531     segm[nbseg].Init(static_cast<Standard_Integer>( p1.X() + curview->GetDx()),
1532                      static_cast<Standard_Integer>(-p1.Y() - curview->GetDy()),
1533                      static_cast<Standard_Integer>( p2.X() + curview->GetDx()),
1534                      static_cast<Standard_Integer>(-p2.Y() - curview->GetDy()));
1535     nbseg++;
1536 #endif
1537     if (nbseg == MAXSEGMENT) {
1538       Draw_Flush();
1539     }
1540     if (Draw_Bounds) {
1541       if (p2.X() > xmax) xmax = p2.X();
1542       if (p2.X() < xmin) xmin = p2.X();
1543       if (p2.Y() > ymax) ymax = p2.Y();
1544       if (p2.Y() < ymin) ymin = p2.Y();
1545     }
1546   }
1547     break;
1548
1549   case PICK :
1550     if (!found) {
1551       Standard_Integer x1 =  (int) p1.X() ;
1552       Standard_Integer y1 =  (int) p1.Y() ;
1553       Standard_Integer x2 =  (int) p2.X() ;
1554       Standard_Integer y2 =  (int) p2.Y() ;
1555       if ((x1 >= xpick + precpick) && (x2 >= xpick + precpick)) break;
1556       if ((x1 <= xpick - precpick) && (x2 <= xpick - precpick)) break;
1557       if ((y1 >= ypick + precpick) && (y2 >= ypick + precpick)) break;
1558       if ((y1 <= ypick - precpick) && (y2 <= ypick - precpick)) break;
1559
1560       Standard_Boolean inside = Standard_True;
1561       if ((x1 > xpick + precpick) || (x2 > xpick + precpick)) {
1562         Standard_Real y = (Standard_Real) y1 +
1563           (Standard_Real) (y2-y1) * (Standard_Real) (xpick+precpick-x1) /
1564             (Standard_Real) (x2 - x1);
1565         if ( (y < ypick+precpick) && (y > ypick - precpick)) {
1566           found = Standard_True;
1567           lastPickParam = (Standard_Real) (xpick - x1) /
1568             (Standard_Real) (x2 - x1);
1569           break;
1570         }
1571         else
1572           inside = Standard_False;
1573       }
1574
1575       if ((x1 < xpick - precpick) || (x2 < xpick - precpick)) {
1576         Standard_Real y = (Standard_Real) y1 +
1577           (Standard_Real) (y2-y1) * (Standard_Real) (xpick-precpick-x1) /
1578             (Standard_Real) (x2 - x1);
1579         if ( (y < ypick+precpick) && (y > ypick - precpick)) {
1580           found = Standard_True;
1581           lastPickParam = (Standard_Real) (xpick - x1) /
1582             (Standard_Real) (x2 - x1);
1583           break;
1584         }
1585         else
1586           inside = Standard_False;
1587       }
1588
1589
1590       if ((y1 > ypick + precpick) || (y2 > ypick + precpick)) {
1591         Standard_Real x = (Standard_Real) x1 +
1592           (Standard_Real) (x2-x1) * (Standard_Real) (ypick+precpick-y1) /
1593             (Standard_Real) (y2 - y1);
1594         if ( (x < xpick+precpick) && (x > xpick - precpick)) {
1595           found = Standard_True;
1596           lastPickParam = (Standard_Real) (ypick - y1) /
1597             (Standard_Real) (y2 - y1);
1598           break;
1599         }
1600         else
1601           inside = Standard_False;
1602       }
1603
1604
1605       if ((y1 < ypick - precpick) || (y2 < ypick - precpick)) {
1606         Standard_Real x = (Standard_Real) x1 +
1607           (Standard_Real) (x2-x1) * (Standard_Real) (ypick-precpick-y1) /
1608             (Standard_Real) (y2 - y1);
1609         if ( (x < xpick+precpick) && (x > xpick - precpick)) {
1610           found = Standard_True;
1611           lastPickParam = (Standard_Real) (ypick - y1) /
1612             (Standard_Real) (y2 - y1);
1613           break;
1614         }
1615         else
1616           inside = Standard_False;
1617       }
1618     found = found || inside;
1619       if (found) {
1620         if (Abs(x2-x1) > Abs(y2-y1)) {
1621           if (Abs(x2-x1) < 1e-5)  lastPickParam = 0;
1622           else
1623             lastPickParam = (Standard_Real)(xpick - x1) /
1624               (Standard_Real)(x2 - x1);
1625         }
1626         else {
1627           if (Abs(y2-y1) < 1e-5)  lastPickParam = 0;
1628           else
1629             lastPickParam = (Standard_Real)(ypick - y1) /
1630               (Standard_Real)(y2 - y1);
1631         }
1632       }
1633     }
1634     break;
1635
1636   case POSTSCRIPT :
1637     {
1638       Standard_Integer x = (Standard_Integer )( (p2.X() - ps_vx) * ps_kx + ps_px);
1639       Standard_Integer y = (Standard_Integer )( (p2.Y() - ps_vy) * ps_ky + ps_py);
1640       (*ps_stream) << x << " " << y << " l\n";
1641     }
1642     break;
1643   }
1644
1645 }
1646
1647 //=======================================================================
1648 //function : MoveTo
1649 //purpose  :
1650 //=======================================================================
1651
1652 void Draw_Display::MoveTo (const gp_Pnt& pt)
1653 {
1654   if (Draw_Batch) return;
1655   if (CurrentMode == PICK) {
1656     if (!found) lastPickP1 = pt;
1657     else return;
1658   }
1659   PtPers = pt;
1660   PtPers.Transform(curview->GetMatrix());
1661   Standard_Real xp = PtPers.X();
1662   Standard_Real yp = PtPers.Y();
1663   if (curview->IsPerspective())
1664   {
1665     Standard_Real ZPers = PtPers.Z();
1666     const Standard_Real aDistance = curview->GetFocalDistance();
1667     if (ZPers < aDistance * precpers)
1668     {
1669       xp=xp * aDistance / (aDistance-ZPers);
1670       yp=yp * aDistance / (aDistance-ZPers);
1671     }
1672   }
1673   MoveTo(gp_Pnt2d(xp,yp));
1674 }
1675
1676 //=======================================================================
1677 //function : DrawTo
1678 //purpose  :
1679 //=======================================================================
1680
1681 void Draw_Display::DrawTo (const gp_Pnt& pt)
1682 {
1683   if (Draw_Batch) return;
1684   if ((CurrentMode == PICK) && found) return;
1685
1686   gp_Pnt pt2 = pt.Transformed(curview->GetMatrix());
1687   Standard_Real xp2 = pt2.X();
1688   Standard_Real yp2 = pt2.Y();
1689
1690   if (curview->IsPerspective())
1691   {
1692     const Standard_Real aZoom     = curview->GetZoom();
1693     const Standard_Real aDistance = curview->GetFocalDistance();
1694
1695     Standard_Real xp1 = PtPers.X();
1696     Standard_Real yp1 = PtPers.Y();
1697     Standard_Real zp1 = PtPers.Z();
1698     Standard_Real zp2 = pt2.Z();
1699     PtPers   = pt2;
1700     if ((zp1 >= aDistance*precpers) && (zp2 >= aDistance*precpers) )
1701     {
1702       return;  // segment is not visible in perspective (behind the eye)
1703     }
1704     else if (zp1 >= aDistance*precpers)
1705     {
1706       xp1=xp1+(xp2-xp1)*(aDistance*precpers-zp1)/(zp2-zp1);
1707       yp1=yp1+(yp2-yp1)*(aDistance*precpers-zp1)/(zp2-zp1);
1708       zp1=aDistance*precpers;
1709       xp1=xp1*aDistance/(aDistance-zp1);
1710       yp1=yp1*aDistance/(aDistance-zp1);
1711       MoveTo( gp_Pnt2d(xp1 * aZoom, yp1 * aZoom) );
1712     }
1713     else if (zp2 >= aDistance*precpers)
1714     {
1715       xp2=xp2+(xp1-xp2)*(aDistance*precpers-zp2)/(zp1-zp2);
1716       yp2=yp2+(yp1-yp2)*(aDistance*precpers-zp2)/(zp1-zp2);
1717       zp2=aDistance*precpers;
1718     }
1719     xp2 = xp2 * aDistance / (aDistance - zp2);
1720     yp2 = yp2 * aDistance / (aDistance - zp2);
1721   }
1722   DrawTo(gp_Pnt2d(xp2,yp2));
1723   if (CurrentMode == PICK) {
1724     if      (!found)    lastPickP1 = pt;
1725     else                lastPickP2 = pt;
1726   }
1727 }
1728
1729 //=======================================================================
1730 //function : Draw
1731 //purpose  :
1732 //=======================================================================
1733
1734 void Draw_Display::Draw (const gp_Pnt& p1, const gp_Pnt& p2)
1735 {
1736   if (Draw_Batch) return;
1737   MoveTo(p1);
1738   DrawTo(p2);
1739 }
1740
1741 //=======================================================================
1742 //function : Draw
1743 //purpose  :
1744 //=======================================================================
1745
1746 void Draw_Display::Draw(const gp_Pnt2d& p1, const gp_Pnt2d& p2)
1747 {
1748   if (Draw_Batch) return;
1749   MoveTo(p1);
1750   DrawTo(p2);
1751 }
1752
1753
1754 //=======================================================================
1755 //function : ViewId
1756 //purpose  :
1757 //=======================================================================
1758
1759 Standard_Integer Draw_Display::ViewId() const
1760 {
1761   if (Draw_Batch) return 0;
1762   return curviewId;
1763 }
1764
1765
1766 //=======================================================================
1767 //function : HasPicked
1768 //purpose  :
1769 //=======================================================================
1770
1771 Standard_Boolean Draw_Display::HasPicked() const
1772 {
1773   if (Draw_Batch) return Standard_False;
1774   return found;
1775 }
1776