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