Back to index

CDrawable.C

 
//----------------------------------------------------------------------------- 
//  $Header: CDrawable.C,v 2.4 97/04/14 14:34:56 messer Exp $ 
// 
//  COOL Program Library   
//  Copyright (C) CERES collaboration, 1996 
// 
//  Implementation of abstract class CDrawable. 
// 
//----------------------------------------------------------------------------- 
#include <iostream.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <strings.h> 
#include <math.h> 
#include "CDrawable.h" 
#include <X11/Xutil.h> 
 
int CDrawable::refCount = 0; 
int CDrawable::vogleInitialized = 0; 
 
CDrawable::CDrawable() 
{ 
   xdisplay = 0;                // can be overwritten by bindWindow() 
   xwindow  = 0; 
   refCount++; 
   psMode     = False; 
   zoomFactor = 0;              // zero for nominal view 
   xzoom      = 0; 
   yzoom      = 0; 
} 
 
CDrawable::~CDrawable() 
{ 
   if (--refCount < 0) refCount = 0; 
   if (refCount == 0 && vogleInitialized) { 
      vexit(); 
      vogleInitialized = False; 
   } 
} 
 
 
void CDrawable::bindWindow(const char*) {} 
 
void CDrawable::setupColors() 
{ 
   // 
   //  First some standard colors not already defined in vogle 
   // 
   mapcolor(Gray, int(0.7*MaxColors), int(0.7*MaxColors), int(0.7*MaxColors)); 
    
   // 
   //  Now fill the color table according to amplitude. 
   //  Amplitude zero is drawn in black. The 12 most high 
   //  amplitudes are set to pure red to prevent X11 from 
   //  running out of non-allocated colormap cells. The eye 
   //  cannot resolve all that shades of red anyhow. 
   //  For the same reason hue values are converted to int 
   //  in order to assign amplitudes with close hue values the 
   //  same color. 
   //  The color generation is according to an exponential 
   //  amplitude distribution and starts at deep blue going 
   //  through green, yellow and ends at pure red. 
   // 
   const int light = 50; 
   const int sat = 100; 
   int colorIndex = Gray+1; 
   int hue, hueOld = 0;    
   int red, green, blue; 
   colors.insert(Black); 
   for (int amplitude=1; amplitude < MaxColors; amplitude++) { 
      if (amplitude < MaxColors-12) { 
         hue = int(double(MaxColors)*(1.-log(amplitude+1)/log(MaxColors))); 
         if (hue == hueOld) 
            colors.insert(colors[amplitude-1]); 
         else { 
            hls2rgb(hue, light, sat, red, green, blue); 
            mapcolor(colorIndex, red, green, blue);                // range 0-255 
            colors.insert(colorIndex); 
            colorIndex++; 
         } 
         hueOld = hue; 
      } 
      else 
         colors.insert(Red); 
   } 
} 
 
 
void CDrawable::display(const char* options) 
{ 
   // 
   //  Check if xdisplay and window already exist. 
   //  If not, open a new display and create new window. 
   // 
 
   if (xdisplay == 0) 
      xdisplay = XOpenDisplay((char*)0); 
   if (xwindow == 0) 
      xwindow = createNewWindow(); 
    
   // 
   //  Get the actual dimension of the window (device coordinates) 
   // 
   XWindowAttributes windowAttributes; 
   XGetWindowAttributes(xdisplay, xwindow, &windowAttributes); 
   width = windowAttributes.width; 
   height = windowAttributes.height; 
    
   // 
   //  Tell vogle which window to draw in. If this is the (first? cv) 
   //  call to vogle we have to initialize the package via  
   //  vinit(). However this should be done only once for 
   //  all instances of CDrawable.  
   // 
   if (!vogleInitialized) { 
      vo_xt_window(xdisplay, xwindow, width, height); 
      vinit("X11"); 
      vogleInitialized = True; 
   } 
   else { 
      vo_xt_set_win(xdisplay, xwindow, width, height); 
   } 
    
   // 
   //  Initialize drawing, define world coordinate system 
   //  If zoomFactor > 1 we also have to calculate the new 
   //  frame according to xzoom, yzoom and zoomFactor. 
   // 
   xdisplay = vo_xt_get_display(); 
   xwindow = vo_xt_get_window(); 
   vsetflush(False); 
   circleprecision(128); 
   if (colors.isEmpty()) setupColors(); 
 
   viewport(-1,1,-1,1); 
   if (zoomFactor > 1) { 
      float xrange = (getRight()-getLeft())/zoomFactor; 
      float yrange = (getTop()-getBottom())/zoomFactor; 
      ortho2(xzoom-xrange/2., xzoom+xrange/2., 
             yzoom-yrange/2., yzoom+yrange/2); 
   } 
   else 
      ortho2(getLeft(), getRight(), getBottom(), getTop()); 
    
   // 
   //  If no new options are given we use the previous settings 
   // 
   if (options != 0 && strcmp(options, "") != 0 ) 
      lastOptions = options; 
 
   // 
   //  Do the drawing provided by the derived class 
   // 
   if (zoomFactor > 1) 
      clipping(True); 
   else 
      clipping(False); 
   psMode = False; 
 
   draw(lastOptions.data());  
    
   vflush(); 
    
   // 
   //  Get rid of queued expose events 
   // 
   XEvent xevent; 
   while (XCheckTypedWindowEvent(xdisplay, xwindow, Expose, &xevent));    
} 
 
 
Window CDrawable::createNewWindow()  
{ 
   // 
   //  Window manager hints 
   // 
   XSizeHints *size_hints = XAllocSizeHints(); 
   XWMHints *wm_hints = XAllocWMHints(); 
   XClassHint *class_hints = XAllocClassHint(); 
         
   // 
   //  Get screen size from display structure macro 
   // 
   int screen_num = DefaultScreen(xdisplay); 
   unsigned int display_width = DisplayWidth(xdisplay, screen_num); 
   unsigned int display_height = DisplayHeight(xdisplay, screen_num); 
         
   // 
   //  Size of window 
   // 
   int x = 0; 
   int y = 0; 
   width = display_width/3; 
   height = int(width*(getTop()-getBottom())/(getRight()-getLeft())); 
   unsigned int border_width = 1; 
    
   // 
   //  Create Window 
   // 
   Window win = XCreateSimpleWindow(xdisplay, RootWindow(xdisplay,screen_num),  
                        x, y, width, height, border_width, BlackPixel(xdisplay, 
                        screen_num), WhitePixel(xdisplay,screen_num)); 
         
   // 
   //  Set size hints for window manager.  The window manager may 
   //  override these settings.  
   // 
   size_hints->flags = PPosition | PSize | PMinSize; 
   size_hints->min_width = width; 
   size_hints->min_height = height; 
         
   // 
   // These calls store window_name and icon_name into 
   // XTextProperty structures and set their other  
   // fields properly. 
   // 
   XTextProperty windowName, iconName; 
   char *window_name = (char*) getName().data(); 
   XStringListToTextProperty(&window_name, 1, &windowName); 
   XStringListToTextProperty(&window_name, 1, &iconName); 
 
   // 
   //  Set the window manager hints 
   // 
   wm_hints->initial_state = NormalState; 
   wm_hints->input = True; 
   wm_hints->flags = StateHint | InputHint; 
 
   class_hints->res_name = 0; 
   class_hints->res_class = "Cool"; 
    
   XSetWMProperties(xdisplay, win, &windowName, &iconName,  
                    0, 0, size_hints, wm_hints, class_hints); 
    
   // 
   //  Display window  
   // 
   XMapRaised(xdisplay, win); 
    
   return win; 
} 
 
 
void CDrawable::storePostScript(const char* filename) 
{ 
   // 
   //  Setup PS driver 
   // 
   voutput((char*)filename);        // redirect output to file  
   vnewdev("pcps");                // new PostScript device 
    
   // 
   //  Define viewport, world coordinates and colors 
   // 
   viewport(-1,1,-1,1); 
   if (zoomFactor > 1) { 
      float xrange = (getRight()-getLeft())/zoomFactor; 
      float yrange = (getTop()-getBottom())/zoomFactor; 
      ortho2(xzoom-xrange/2., xzoom+xrange/2., 
             yzoom-yrange/2., yzoom+yrange/2); 
   } 
   else 
      ortho2(getLeft(), getRight(), getBottom(), getTop()); 
   setupColors();        // new colormap for PostScript device 
    
   // 
   //  Perform the actual drawing, use previously defined option string  
   // 
   psMode = True; 
   clipping(True); 
   draw(lastOptions.data()); 
   vflush(); 
    
   // 
   //  Back to old device 
   // 
   vo_xt_window(xdisplay, xwindow, width, height); 
   vinit("X11"); 
} 
 
 
void CDrawable::printPostScript(const char* printer) 
{   
   CString filename, device, command; 
    
   filename = tempnam("/tmp", "COOL");                // get temporary file name  
   device   = printer; 
   command  = "(lp -d" + device + " " + filename + "; rm -f " + filename + ")&"; 
    
   storePostScript(filename.data()); 
   system(command.data()); 
} 
 
 
#define VALUE(n1, n2, h)  ((h < 60) ? (n1 + (n2-n1)*h/60) : ((h<180) ? \ 
                                (n2) : ((h<240) ? (n1+(n2-n1)*(240-h)/60) : (n1)))) 
 
void CDrawable::hls2rgb(int hue, int light, int sat, int &red, int &green, int &blue) 
{ 
        double h = (double) hue; 
        double l = (double) light/100; 
        double s = (double) sat/100; 
        double m1, m2; 
        double r, g, b; 
 
        if (l<= 0.5) 
                m2 = l*(1 + s); 
        else 
                m2 = l + s - l*s; 
        m1 = 2*l - m2; 
        if ((s == 0) && (h == 0)) { 
                r = l; g = l; b = l; 
        } 
        else { 
                r = VALUE(m1, m2, (((h+120) > 360) ? (h-240) : (h+120))); 
                g = VALUE(m1, m2, h); 
                b = VALUE(m1, m2, (((h-120) < 0) ? (h+240) : (h-120))); 
        } 
         
        red =  (int) (r * 255); 
        green = (int) (g * 255); 
        blue = (int) (b * 255); 
} 
 
 
void CDrawable::zoom() 
{ 
   float wx, wy; 
    
   locator(&wx, &wy); 
   if (wx > getRight() || wx < getLeft() || 
       wy > getTop()   || wy < getBottom()) return; 
    
   // 
   //  Each zoom click inceases the zoom by a factor of 2 
   // 
   if (zoomFactor < 1) zoomFactor = 1; 
   zoomFactor *= 2; 
   xzoom = wx; 
   yzoom = wy; 
   display((char*)0); 
} 
 
 
void CDrawable::zoomOut() 
{ 
   // 
   //  Zoom out leaving the current view center untouched. 
   // 
   zoomFactor /= 2; 
   if (zoomFactor < 1) zoomFactor = 1; 
   display((char*)0); 
} 
 
 
void CDrawable::resetZoom() 
{ 
   zoomFactor = 0; 
   display((char*)0); 
} 
 
 
void CDrawable::locatePoint() 
{ 
   float wx, wy; 
    
   locator(&wx, &wy); 
   if (wx > getRight() || wx < getLeft() || 
       wy > getTop()   || wy < getBottom()) return; 
    
   cout << '(' << wx << ',' << wy << ')' << endl; 
   cout.flush(); 
} 
 
 

Back to index