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