casa
$Rev:20696$
|
00001 //# Display.h: Display module header file 00002 //# Copyright (C) 1994,1995,1996,1997,1998,1999,2000 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id$ 00027 00028 #ifndef TRIALDISPLAY_DISPLAY_H 00029 #define TRIALDISPLAY_DISPLAY_H 00030 00031 //#include <graphics/X11/X11Util.h> 00032 #include <display/Display/DisplayEnums.h> 00033 #include <display/Display/PixelCanvasColorTable.h> 00034 #include <display/Display/PixelCanvas.h> 00035 #include <display/Display/WorldCanvas.h> 00036 00037 // Go ahead and include X11 stuff for now 00038 //#include <display/Display/X11PixelCanvasColorTable.h> 00039 //#include <display/Display/X11PixelCanvas.h> 00040 00041 // Include Simple{World,Pixel}CanvasApp stuff 00042 #include <display/Display/SimplePixelCanvasApp.h> 00043 #include <display/Display/SimpleWorldCanvasApp.h> 00044 00045 namespace casa { //# NAMESPACE CASA - BEGIN 00046 00047 // 00048 // <module> 00049 // 00050 // <summary>A module providing graphical display classes for use with AIPS++ </summary> 00051 // 00052 // <prerequisite> 00053 // <li> <linkto class="Vector">Vector</linkto> 00054 // <li> <linkto class="Matrix">Matrix</linkto> 00055 // </prerequisite> 00056 // 00057 // <reviewed reviewer="None yet" date="yyyy/mm/dd" demos=""> 00058 // </reviewed> 00059 // 00060 // <etymology> 00061 // Module provides classes for an Image Display Library 00062 // </etymology> 00063 // 00064 // <synopsis> The purpose of the Display library is twofold: 1) to provide a 00065 // set of tools for the AIPS++ programmer which make it easier to create 00066 // drawing windows and use those drawing windows as output devices for 00067 // graphical primitives, including images, and 2) to provide a set of higher- 00068 // level classes to display datasets in a number of ways (images, contours, ...) 00069 // as well as classes to help build an application that needs to display 00070 // several datasets. 00071 // 00072 // A design goal is to have Display Library applications portable to 00073 // another graphics system by augmenting the Library to provide an 00074 // interface to that graphics system. 00075 // 00076 // <h1><center><Display Library Contents></center></h1> 00077 // 00078 // <ol> 00079 // <li> <a href="#Overview">Display Library Overview</a> 00080 // <li> <a href="#PixelCanvas">PixelCanvas</a> 00081 // <ol> 00082 // <li> <a href="#PCDrawingCommands">Drawing Commands</a> 00083 // <li> <a href="#PCEvents">Event Handling</a> 00084 // <li> <a href="#PCCaching">Caching Mechanism</a> 00085 // <li> <a href="#PCColormaps">Colormap System</a> 00086 // </ol> 00087 // <li> <a href="#WorldCanvas">WorldCanvas</a> 00088 // <ol> 00089 // <li> <a href="#WCDrawingCommands">Drawing Commands</a> 00090 // <li> <a href="#WCEvents">Event Handling</a> 00091 // <li> <a href="#WCHandlers">Other Handlers</a> 00092 // </ol> 00093 // <li> <a href="#WorldCanvasHolder">WorldCanvasHolder</a> 00094 // <li> <a href="#DisplayData">DisplayData</a> 00095 // <li> <a href="#Zoomer">Zoomer</a> 00096 // <li> <a href="#Animator">Animator</a> 00097 // </ol> 00098 // 00099 // <hr> 00100 // 00101 // <h2><a name="Overview">Display Library Overview</a></h2> 00102 // 00103 // The Display library is a set of tools for the AIPS++ programmer which make 00104 // it easier to create drawing windows and use those drawing windows as output 00105 // devices for graphical primitives, including images. To some extent, the 00106 // Display Library consists of two parts. One part is a set of device 00107 // indepentent classes that give the basic functionality for data display. The 00108 // classes of the first group are quite generic and can basically be used for 00109 // any application that needs an interactive display window and these classes 00110 // not tied to AIPS++ data sets or AIPS++ coordinate systems. They make only 00111 // very few assumptions for what they will be used. The second part is more 00112 // concerned with transforming data sets into objects that are understood by 00113 // the first layer, as well as classes that should make it easier to build a 00114 // full application that displays data. The classes of the second group can be 00115 // quite data specific. 00116 // 00117 // The main classes from the first group are the PixelCanvas, the WorldCanvas 00118 // and the ColorMap classes. The PixelCanvas conceptually corresponds to the 00119 // window on the screen. It works only in 'screen' units, ie. screen pixel 00120 // coordiantes and screen data values. The PixelCanvas is, to some extent, the 00121 // interface between Aips++ and the display hardware and graphics environment 00122 // (e.g. X11). The WorldCanvas is mostly an interface layer between the 'real 00123 // world' and the PixelCanvas. Its main responsibility is to transform drawing 00124 // instruction that are specified in world coordinates and world values to the 00125 // corresponding instructions of the PixelCanvas specified in pixel 00126 // coordinates and pixel values. The PixelCanvas and the WorldCanvas are 00127 // intended to be relatively 'raw' devices. With this we mean that both 00128 // classes have basically no knowledge of the classes that use these Canvases 00129 // to display data. In effect, The PixelCanvas does not know what a 00130 // WorldCanvas is. The reason to make the canvases relatively ignorant, is 00131 // that by putting in as few assumptions as possible in the canvases, they 00132 // (hopefully) can be used in a very wide range of applications. For example, 00133 // it is quite easy to make a 2D colormap editor (an application that is quite 00134 // different from e.g. displaying a contour map) based on the PixelCanvas or 00135 // on the WorldCanvas. To achieve that only a few assumption have to be built 00136 // in in the canvases, the canvases communicate to other classes via event 00137 // handlers that these other classes have to register with the canvases. Also 00138 // the PixelCanvas communicates with the WorldCanvas thourg such event 00139 // handlers. For example, if the window corresponding to the Pixelcanvas is 00140 // resized by the user, this generates a refresh event and the Pixelcanvas 00141 // calls the refresh event handlers registered with the PixelCanvas. When a 00142 // WorldCanvas is created, the first thing the WorldCanvas does is to install 00143 // a number of event handlers on the PixelCanvas. This means that if e.g. the 00144 // refresh event occurs on the PixelCanvas, the WorldCanvas is notified and 00145 // takes the necessary action. This scheme of communication through event 00146 // handlers is used throughout the Display Library. The classes that generate 00147 // events do not have to know what classes consume these events, the only 00148 // thing that is defined is the interface (and content) of the event. This 00149 // means that one could build a class on top of the PixelCanvas that is quite 00150 // different from the WorldCanvas. 00151 // 00152 // To keep the WorldCanvas as generic as possible, the coordinate system the 00153 // WorldCanvas uses to transform from screen pixels to world coordinates and 00154 // back is not stored in the WorldCnvas but is also defined through an event 00155 // handler (a CoordinateHandler). If the WorldCanvas has to do a coordinate 00156 // transformation, it asks the CoordinateHandler to do this. In many cases, 00157 // this CoordinateHandler will use a standard Aips++ CoordinateSystem to do 00158 // the transformation, but this is not a requirement, and the programmer can 00159 // implement any tranformation required, as long as it satisfies the interface 00160 // of the CoordinateHandler. 00161 // 00162 // The features of the first group include 00163 // 00164 // <ul> 00165 // <li> Multi-layer programming library (PixelCanvas, WorldCanvas, Application) 00166 // <li> PixelCanvas Interface which abstracts the underlying graphics library. 00167 // <li> Colormap system allows applications to function independent of the 00168 // number of available colors. 00169 // <li> System color resources can be changed while running. 00170 // <li> Drawing commands in world or pixel coordinates and values. 00171 // <li> Events represented in world and pixel coordinates. 00172 // </ul> 00173 // 00174 // The classes of the second group have a quite different purpose. They are 00175 // much more concerned with building an application that needs to display one 00176 // or more aips++ datasets in a number of ways. 00177 // 00178 // To make the link between the relatively generic display classes 00179 // (PixelCanvas, WorldCanvas etc) and classes quite specific for displaying 00180 // Aips++ datasets, an intermediate class is required. This class is called 00181 // the WorldCanvasHolder. The main role of the WorldCanvasHolder is to catch 00182 // the events that occur on a WorldCanvas and distribute these events to the 00183 // data that is being displayed on the Worldcanvas. Another important role of 00184 // the WorldCanvasHolder is that it is the class that is used to control what 00185 // is actually displayed on the WorldCanvas. One important design requirement 00186 // for the Display Library was that, from the programmer point of view, it 00187 // should be easy to display more than one dataset in a window at the same 00188 // time. A standard example is a contourmap on top of a greyscale image. 00189 // Consequently, one can register more than one display object with the 00190 // WorldCanvasHolder so that they are displayed at the same time. 00191 // 00192 // One important aspect that the WorldCanvasHolder takes care of is the 00193 // sizeControl of the WorldCanvas. If a refresh event happens on the 00194 // WorldCanvas, before invoking the refresh event handlers installed on the 00195 // WorldCanvas, the WorldCanvas invokes a sizeControl event. The meaning of 00196 // this event is to ask the object that draws on the WorldCanvas (e.g. the 00197 // WorldCanvasHolder) to check if the state of the WorldCanvas is ok so that 00198 // it can be drawn on, and if it is not ok, that the state of the WorldCanvas 00199 // be modified. For example, if an image is drwan as a pseudeocolor image and 00200 // the window (or WorldCanvas) is much larger that the data array, one wants 00201 // to expand the data array so that it fills more or less the window. One way 00202 // of doing this is to do this by pixelreplication. But this means that there 00203 // are requirements on the size of the area that the WorldCanvas uses for 00204 // drawing the image (it has to be a integer multiple of the size of the data 00205 // array. This explains the name sizeControl). It is the responsibility of the 00206 // objects that draw on the WorldCanvas, to get these size right. What in 00207 // practice happens is that the WorldCanvasHolder asks the display objects to 00208 // sort this out and set the correct size on the WorldCanvas. Once this is 00209 // sorted out, the WorldCanvas is in the coreect state and things can be 00210 // drawn. The name sizeControl is not entirely correct. The obvious use of 00211 // this mechanism is as in the example described above, but the problem is 00212 // more general: before display objects can draw on the WorldCanvas they have 00213 // to be sure that the WorldCanvas is in the correct state and possibly they 00214 // have to modify the attributes of the WorldCanvas. Because more than one 00215 // display object can draw on the WorldCanvas, this has to be done before the 00216 // actual drawing occurs (because the display objects do not know if there are 00217 // more than one display objects drawing on the WorldCanvas). 00218 // 00219 // Another requirement for the Display Library was that no distinction should 00220 // be made based on how data is displayed. For example, displaying an image as 00221 // a pseudocolor image on the screen should, from the Display Library point of 00222 // view, be the same operation as displaying that image as a contourmap. This 00223 // means that the display object is quite an 'abstract' class. Display Objects 00224 // in the Display Library are called DisplayData (or better: are derived from 00225 // DisplayData). The role of the DisplayData is, using a certain algorithm, to 00226 // transform data into one or more draw instructions for the WorldCanvas. An 00227 // example is ImageDisplayData that takes an Aips++ dataset and display its 00228 // contents as images, Another example would be ContourDisplayData that draws 00229 // images as contourmaps. Also here, the communication to the DisplayData goes 00230 // via calling event handlers. Depending on what happens (e.g. a refresh 00231 // event, or a position event), the WorldCanvasHolder (who catches these 00232 // events from the WorldCanvas), invokes member functions of the DisplayData 00233 // registered with the WorldCanvasHolder (so to a large extent, a DisplayData 00234 // is an event handler on the WorldCanvasHolder). For example, if a refresh 00235 // event happens, the WorldCanvasHolder will ask the DisplayData to draw what 00236 // they should draw. If a programmer wants to implement a new way of 00237 // displaying data, what this programmer has to do is to implement a new class 00238 // derived from DisplayData that computes whatever it has to compute (say a 00239 // volume rendering of a datacube) and transform this into draw instructions 00240 // for the WorldCanvas (in this example, just call WorldCanvas.drawImage() on 00241 // the result of the volume rendering). A class derived from DisplayData does 00242 // not need to have an Aips++ dataset, but one could for example image a 00243 // DisplayData class that reads positions from a catalog and plots these 00244 // positions on the WorldCanvas. 00245 // 00246 // Because everything in the Display Library is event driven, it is also easy 00247 // to make applications that require more than one display window. The 00248 // programmer only has to decide how to link the various windows by installng 00249 // the appropriate event handlers on the various classes. An example of how 00250 // this can be done is the Zoomer class. This class is a high-level class that 00251 // catches position events on the WorldCanvases (possibly more than one) that 00252 // are registered with the Zoomer. If the right event happens on one of the 00253 // WorldCanvases (say, the user is rubberbanding a rectangle), the Zoomer sets 00254 // the correct attributes on all the WorldCanvases registered with the Zoomer 00255 // (meaning: it defines the area to which should be zoomed in) and invokes a 00256 // refresh event on all these WorldCanvases. This means that all the 00257 // WorldCanvases will zoom in synch. 00258 // 00259 // Another design requirement of the Display Library was that it should be 00260 // easy to display movies, and the DisplayData are build with sequences in 00261 // mind (as is clear from their interface). The programmer is free to define 00262 // what a sequence really means, but it is probably best to keep the structure 00263 // of the sequence in a DisplayData logical to at least some extent. But there 00264 // is no real requirement on the structure of the sequence. Movies can be 00265 // controlled using the Animator class. The easy way is to use indices, but 00266 // there is a generic way of defining movies using restrictions (see later 00267 // what these mean). So a sequence does not have to correspond to a 'physical' 00268 // sequence in one datastructure (channels in a cube for example), but can be 00269 // made of representations of different datasets (e.g. blinking), or more 00270 // exotic combinations of different datasets displayed in different form 00271 // (e.g. blink between a greyscale and a contourmap, if such a thing would be 00272 // useful). This system is very flexible and there are no real limits to what 00273 // a movie really means. 00274 // 00275 // An important concept in the Display Library is that of Attributes (and 00276 // their use as restrictions). Attributes are name-value pairs. Many classes 00277 // of the Display Library have a buffer where they can store these Attributes. 00278 // They can be used for various things (see AttributeBuffer for a number of 00279 // examples). One applications is that a uniform userinterface can be defined 00280 // for changing attributes of a class (meaning internal members), but since 00281 // Attributes can have an arbitrary name, they can be used to place (almost) 00282 // any kind of information on classes <em> at run time</em>. This provides a 00283 // mechanism of distributing information in a display aplication, while at 00284 // compile time it is not yet defined what that information is (name, type, 00285 // etc). 00286 // 00287 // An important application of Attributes is their use as 00288 // <em>restrictions</em>: they are used to select which data is actually 00289 // displayed. DisplayData classes, like ImageDisplayData, are supposed to have 00290 // defined, for each distinct representation that they can draw, one or more 00291 // Attributes, specifically defined to select what data is displayed. These 00292 // Attributes are in a separate (or several separate) AttributeBuffer, called 00293 // the <em>restriction buffer</em>. Also the WorldCanvasHolder has such a 00294 // restriction buffer whose content should be controlled by the application 00295 // programmer. If a refresh happens, the WorldCanvasHolder, after the 00296 // sizeControl step, asks each DisplayData that is registered with the 00297 // WorldCanvasHolder to draw itself, by calling the refreshEH() member of each 00298 // DisplayData. The first thing that a DisplayData should do it to see if the 00299 // restrictions that are placed on the WorldCanvasHolder are compatible with 00300 // this DisplayData and/or check with which element of the DisplayData the 00301 // restriction buffer WorldCanvasHolder is compatible. If the DisplayData has 00302 // compatible data, it should draw this data. An example may make this process 00303 // clearer. An ImageDisplayData is a class derived from DisplayData that 00304 // displays the 2D slices from a n-dimensional dataset on a canvas (for 00305 // example the channels from a datacube). An ImageDisplayData has two general 00306 // restrictions (meaning they apply to all channels): the names of the axes 00307 // ("xAxisName" = "Ra" and "yAxisName" = "Dec"). Since an ImageDisplayData 00308 // (possibly) consists of a number of channels, additional restrictions exist, 00309 // but these have a different value for each element (ie. channel). In the 00310 // case of an ImageDisplayData, each 2D subset has defined "zIndex" and 00311 // "zValue", the first has the value of the pixelcoordinate of the 2D image 00312 // (in our example channel number), the second has the value of the 00313 // WorldCoordinate of centre of the 2D image (in our example the velocity of 00314 // the channel). So to display a channel, a programmer has to set 3 00315 // restrictions on the WorldCanvasHolder: "xAxisName", "yAxisName" to select 00316 // channels from a datacube and set these to "Ra" and "Dec" (or whatever is in 00317 // the header of the data), plus a restriction to select the actual channel, 00318 // e.g. set "zIndex" to 20 to select channel 20, or "zValue" to 1200.0, to 00319 // select the channel corresponding to velocity 1200.0. To display a position 00320 // velocity image, one would have to specify e.g. "xAxisName" = "Dec" and 00321 // "yAxisName" = "Velocity" and set "zValue" to 5.23443311 (the Ra of the 00322 // slice you want to look at). 00323 // 00324 // To determine if restrictionbuffers match, one can simply use the member 00325 // matches() of an AttributeBuffer. The logic of matching restrictions is 00326 // perhaps a bit distorted: restrictions (or Attributes in general) of 00327 // different names <em> always match</em>. So if a DisplayData has a 00328 // restriction called "A" and the WorldCanvasHolder specifies "B", the 00329 // DisplayData should draw itself. Restrictions (and Attributes) can have some 00330 // tolerance. In our example we could have specified "zValue" to be 1200.0, 00331 // plus or minus 5.0. This obviously can be used e.g. to match the channels of 00332 // two data cubes that are on a different velocity grid. The Animator class, 00333 // who can be used to make movies, completely relies on this restriction 00334 // mechanism. 00335 // 00336 // 00337 // 00338 // <hr> 00339 // 00340 // <h2><a name="PixelCanvas">The PixelCanvas</a></h2> 00341 // 00342 // The PixelCanvas display library defines an interface to an underlying 00343 // 2D graphics library. 00344 // 00345 // The design of the PixelCanvas emphasizes the following features: 00346 // 00347 // <ul> 00348 // <li> Straightforward drawing interface using simple Aips++ array types 00349 // <li> Enhanced event handling - Event classes can be derived from to 00350 // add extra functionality. 00351 // <li> Advanced caching system - User can create sequences of drawing commands 00352 // for later recall. Sequences can be compacted and stored into 00353 // native structures for increased drawing performance. 00354 // <li> Ability to register and use several colormaps in the same window at 00355 // the same time. 00356 // <li> Minimize the dependency on the underlying graphics system, in 00357 // this case, X11. 00358 // </ul> 00359 // 00360 // 00361 // <h3><a name="PCDrawingCommands">PixelCanvas Drawing Commands</a></h3> 00362 // 00363 // PixelCanvas drawing commands accept simple AIPS++ objects. Presently the 00364 // drawing commands accept points as Vector<t>'s, where t can be 00365 // any scalar type but Bool. Bool images are not supported because a Bool 00366 // cannot represent a color index. Complex values are not supported because 00367 // there are many ways of creating a single scalar value from complex 00368 // values. 00369 // 00370 // 00371 // <h3><a name="PCEvents">PixelCanvas Event Handling</a></h3> 00372 // 00373 // There are 3 kinds of events the PixelCanvas reports 00374 // 00375 // <ol> 00376 // <li> refresh event - sent when the canvas must be redrawn. 00377 // <li> position event - sent when a button or key is pressed. 00378 // <li> motion event - sent when the mouse moves over the cursor. 00379 // </ol> 00380 // 00381 // Applications handle 00382 // <linkto class=PixelCanvas>PixelCanvas</linkto> events by creating 00383 // <linkto class=PixelCanvas>PixelCanvas</linkto> event handlers 00384 // that must be derived from the appropriate event class, either 00385 // <linkto class=PCRefreshEH>PCRefreshEH</linkto>, 00386 // <linkto class=PCPositionEH>PCPositionEH</linkto>, or 00387 // <linkto class=PCMotionEH>PCMotionEH</linkto>. The () operator 00388 // must be overridden and implemented by responding to the 00389 // information contained in the 00390 // <linkto class=PCRefreshEvent>PCRefreshEvent</linkto>, 00391 // <linkto class=PCPositionEvent>PCPositionEvent</linkto>, or 00392 // <linkto class=PCMotionEvent>PCMotionEvent</linkto>, as appropriate. 00393 // 00394 // 00395 // <h3><a name="PCCaching">PixelCanvas Caching Mechanism</a></h3> 00396 // 00397 // There is a system for creating sequences of commands. It works 00398 // be turning on caching, performing drawing commands, then shutting 00399 // it off. An id is returned to the user to recall the stored 00400 // sequence. This gives the user control over what is to be cached 00401 // while still abstracting the business of caching. 00402 // 00403 // The cache system improves drawing speed by storing drawing data 00404 // in native library formats. 00405 // 00406 // Data stored in native formats means that, for the X11PixelCanvas, 00407 // 00408 // <ul> 00409 // <li> images are stored in terms of pixels as XImages, 00410 // <li> coordinate positions are stored how X likes them (upper left is 0,0), 00411 // <li> lines are stored as XLines or XSegments, as appropriate 00412 // <li> Points are stored as XPoints. 00413 // <li> Pixmap Text is stored as drawing strings 00414 // <li> Stroked Text is stored as XSegments or XLines 00415 // </ul> 00416 // 00417 // It is the responsibility of the user to rebuild display lists 00418 // when necessary. Normally this means when the canvas changes 00419 // size or colormap distribution (if colormaps are in use). 00420 // 00421 // 00422 // <h3><a name="PCColormaps">PixelCanvas Colormap System</a></h3> 00423 // 00424 // The PixelCanvas colormap system design was one of the most difficult 00425 // design problems we faced in building this system. The design goals 00426 // were as follows: 00427 // 00428 // <ol> 00429 // <li> Wanted to be able to pretend we had multiple simultaneous 00430 // colormaps available in some display window. 00431 // <li> Wanted to allow for but not demand that multiple windows 00432 // share the same hardware colormap. 00433 // <li> Wanted to distribute the same colormap to different windows 00434 // potentially displaying on different terminals. 00435 // <li> Wanted to allow for customizing the colormaps, and allow for 00436 // data-dependent colormaps. 00437 // <li> Wanted to be able to resize the available colormap while 00438 // a Display library application was running. 00439 // </ol> 00440 // 00441 // The constraints above have driven us to the following scheme: 00442 // 00443 // <ol> 00444 // <li> Create something called a 00445 // <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto> 00446 // and let it define a table of available colors for one or more 00447 // <linkto class="PixelCanvas">PixelCanvas</linkto>es and be responsible 00448 // for interfacing to the underlying graphics system's color allocation 00449 // facilities. Through the 00450 // <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto> 00451 // one can abstract away the underlying graphic library's tedious and 00452 // cumbersome constructs and functions required to manage color resources 00453 // and visuals and provide a high-level interface based on concepts 00454 // that are better understood. This interface is implemented as the 00455 // constructors for the classes derived from the 00456 // <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto> 00457 // class. 00458 // 00459 // <li> Define a <linkto class=Colormap>Colormap</linkto> to mean not a 00460 // table of colors, but rather a function that takes a floating-point 00461 // parameter in [0.0,1.0] and returns an RGB triple. This function can 00462 // then be used to fill some arbitrary number of consecutive colorcells. 00463 // Allow for <linkto class=Colormap>Colormap</linkto>s to be of a fixed 00464 // size if needed (then they are called 'rigid') 00465 // and design them for derivation so custom colormaps can be created 00466 // and used in this system. 00467 // 00468 // <li> Define a <linkto class=ColormapManager>ColormapManager</linkto> to be 00469 // responsible for dynamically partitioning its 00470 // <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto> 00471 // into chunks, one chunk for each registered 00472 // <linkto class=Colormap>Colormap</linkto>, allowing for rigid 00473 // <linkto class=Colormap>Colormap</linkto>s (that must be for some reason 00474 // of a particular size) and weights to give greater color resolution 00475 // to certain maps. Make it responsible for filling in the color based 00476 // on its distribution of <linkto class=Colormap>Colormap</linkto>s 00477 // in the <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>. 00478 // 00479 // <li> Allow for <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>s 00480 // to be shared by more than one <linkto class="PixelCanvas">PixelCanvas</linkto>, 00481 // and allow <linkto class="PixelCanvas">PixelCanvas</linkto>es to share 00482 // <linkto class=Colormap>Colormap</linkto>s. 00483 // 00484 // <li> Try to abstract away all this mess by placing gateways to necessary 00485 // functionality in the <linkto class="PixelCanvas">PixelCanvas</linkto> 00486 // itself. For example images are drawn on the 00487 // <linkto class="PixelCanvas">PixelCanvas</linkto> through the following 00488 // process: 00489 // 00490 // <ol> 00491 // <li> register a <linkto class=Colormap>Colormap</linkto> with the 00492 // <linkto class="PixelCanvas">PixelCanvas</linkto> (needed only once). 00493 // <li> set the active colormap to the one used in step 1. 00494 // <li> create an image whose values range from 0 to N-1, where N is the size 00495 // of the active colormap 00496 // (<linkto class="PixelCanvas">PixelCanvas</linkto>::getColormapSize()). 00497 // <li> call <linkto class="PixelCanvas">PixelCanvas</linkto>::mapToColor(). 00498 // to convert to color values. 00499 // <li> call <linkto class="PixelCanvas">PixelCanvas</linkto>drawImage() 00500 // with the Matrix of color values 00501 // </ol> 00502 // 00503 // The color image can be reused as long as the distribution of colors 00504 // on the 00505 // <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto> 00506 // doesn't change. Any such change will trigger a refresh event with the 00507 // reason Display::ColorTableChange on the affected 00508 // <linkto class="PixelCanvas">PixelCanvas</linkto>. 00509 // This process can also be used to draw other primitives that each have 00510 // a value associated with it. 00511 // Several colormaps can be switched between by setting the active 00512 // colormap and querying the range, and using the mapToColor function. 00513 // 00514 // <li> Implement a function that resizes the 00515 // <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>, 00516 // forcing a redistribution of colormaps on affected 00517 // <linkto class="PixelCanvas">PixelCanvas</linkto>es followed by a 00518 // refresh event. This ultimately causes a reallocation of writable 00519 // color cells on the underlying graphics library and can be 00520 // used to increase or decrease the number of color cells available to 00521 // the <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto> 00522 // and hence to the application. This mechanism can be used to recover 00523 // allocated color cells from the system map released by other applications 00524 // when they exit, or to balance color resources between two or more 00525 // applications. 00526 // 00527 // </ol> 00528 // 00529 // <hr> 00530 // 00531 // <h2><a name="WorldCanvas">The WorldCanvas</a></h2> 00532 // 00533 // The <linkto class=WorldCanvas>WorldCanvas</linkto> is intended to 00534 // serve as a world-coordinate plotting canvas 00535 // 00536 // 00537 // <h3><a name="WCDrawingCommands">WorldCanvas DrawingCommands</a></h3> 00538 // 00539 // The <linkto class=WorldCanvas>WorldCanvas</linkto> drawing commands 00540 // expect to be given world coordinate values for position information. 00541 // 00542 // 00543 // <h3><a name="WCEvents">WorldCanvas Event Handling</a></h3> 00544 // 00545 // The <linkto class=WorldCanvas>WorldCanvas</linkto> event handling 00546 // is similar to the <linkto class=PixelCanvas>PixelCanvas</linkto> 00547 // event handling, but the <linkto class=WorldCanvas>WorldCanvas</linkto> 00548 // events contain extra information which includes the world coordinate 00549 // and linear coordinate position of the mouse pointer. The same 00550 // basic three events are available: 00551 // 00552 // <ol> 00553 // <li> refresh event - sent when the canvas must be redrawn. 00554 // <li> position event - sent when a button or key is pressed. 00555 // <li> motion event - sent when the mouse moves over the cursor. 00556 // </ol> 00557 // 00558 // Applications handle 00559 // <linkto class=WorldCanvas>WorldCanvas</linkto> events by creating 00560 // <linkto class=WorldCanvas>WorldCanvas</linkto> event handlers 00561 // that must be derived from the appropriate event class, either 00562 // <linkto class=WCRefreshEH>WCRefreshEH</linkto>, 00563 // <linkto class=WCPositionEH>WCPositionEH</linkto>, or 00564 // <linkto class=WCMotionEH>WCMotionEH</linkto>. The () operator 00565 // must be overridden and implemented by responding to the 00566 // information contained in the 00567 // <linkto class=WCRefreshEvent>WCRefreshEvent</linkto>, 00568 // <linkto class=WCPositionEvent>WCPositionEvent</linkto>, or 00569 // <linkto class=WCMotionEvent>WCMotionEvent</linkto>, as appropriate. 00570 // 00571 // 00572 // <h3><a name="WCHandlers">Other WorldCanvas Handlers</a></h3> 00573 // 00574 // Other handlers can be registered with the WorldCanvas to customize: 00575 // <ul> 00576 // <li> World Coordinate transformations 00577 // <li> Linear resampling algorithm 00578 // <li> Data scaling methods 00579 // <li> Size control function 00580 // </ul> 00581 // 00582 // 00583 // <h2><a name="WorldCanvasHolder">The WorldCanvasHolder</a></h2> 00584 // 00585 // The WorldCanvasHolder is a user of a WorldCanvas. It installs handlers on 00586 // the WorldCanvas for each event a WorldCanvas can generate. The main role 00587 // of the WorldCanvasHolder is to allow to have more than one DisplayData 00588 // object draw on a WorldCanvas (e.g contours on top of an image). A number 00589 // of DisplayDatas can be registered with a WorldCanvasHolder, and the 00590 // WorldCanvasHolder passes WorldCanvas events to these DisplayData. 00591 // To control what is displayed on a WorldCanvas, the programmer can put 00592 // restrictions on a WorldCanvasHolder. Only those DisplayData do actually 00593 // draw whose restrictions match those of the WorldCanvasHolder. See the 00594 // example given above, or have a look at the doc of the Animator. 00595 // 00596 // <h2><a name="DisplayData">The DisplayData Interface</a></h2> 00597 // 00598 // A DisplayData is the class that transforms data (in whatever form: an 00599 // image, a cube, a catalog or whatever) into drawing instructions for the 00600 // WorldCanvas. A DisplayData is the 'workhorse' of the display libary: here 00601 // is defined in what way on can represent data. If one want to add a new way 00602 // of displaying data to aips++, they only thing that has to be done is to 00603 // write a new class, derived from DisplayData, that computes this new 00604 // representation and draws it. For example, if one would want to add volume 00605 // rendering to aips++, one would have to write a class that computes this 00606 // volume rendering (e.g. using some hot-gas algorithm), and draw the result 00607 // of this on a WorldCanvas (ie. simply WorldCanvas.drawImage() on the 00608 // result). DisplayDatas are registered witha WorldCanvasHolder and the 00609 // restriction mechanism is used to select what is being 00610 // displayed. DisplayDatas are also responsible for defining the 00611 // WorldCoordinate system of the WorldCanvas (they have an interface that can 00612 // be called (indirectly) by the WorldCanvas to do the transformations), as 00613 // wel las they have to insure that the state of the WorldCanvas is ok (the 00614 // sizeControl, see above). An example of a DisplayData is the 00615 // ImageDisplayData class, that draws pseudocolor images from a data set. 00616 // 00617 // <h2><a name="Zoomer">The Zoomer</a></h2> 00618 // 00619 // Zooming is done by setying the linear coordinates of the WorldCanvas to 00620 // define the zoom area (using a set function of the WorldCanvas) and force a 00621 // refresh of the WorldCanvas. The Zoomer class defines the userinterface for 00622 // zooming. One can register one (or more) WorldCanvas with a Zoomer. This 00623 // Zoomer installs a position event handler on the WorldCanvas that listens 00624 // to certain key- and mouse events. The Zoomer defines a default 00625 // userinterface, but this can be re-defined. A Zoomer can also handle more 00626 // than one WorldCanvas, so it is easy to let different WorldCanvases zoom in synch. 00627 // 00628 // <h2><a name="Animator">The Animator</a></h2> 00629 // 00630 // The role of the Animator is to give an easy way of controling what is 00631 // displayed on one or more WorldCanvases. By specifying how an Animator 00632 // controls what is displayed (by using indices, world coordinates or 00633 // restrictions), the Animator sets the necessary restrictions on the 00634 // WorldCanvasHolders that are registered with the Animator, and forces a 00635 // refresh on all of them. All WorldCanvasHolder registered on an Animator 00636 // move in synch. 00637 // 00638 // 00639 // 00640 00641 // <hr> 00642 // 00643 // <motivation> 00644 // Need to provide some usefull tools to assist in developing graphical 00645 // C++ applications, addressing the problems encountered in trying to 00646 // use other graphical libraries. 00647 // </motivation> 00648 // 00649 // <hr> 00650 // This section is intended as information about what tasks remain to be 00651 // accomplished for the Display library. 00652 // 00653 // The following list illustrates work remaining at the PixelCanvas level: 00654 // 00655 // <todo asof="1997/10/06"> 00656 // <li> <b>PixelCanvas</b>: change/add PixelCanvas interface to use Matrices for multiple 00657 // vector graphic primitives, and use those interfaces at the 00658 // WorldCanvas level. 00659 // <li> compact sequences of drawPoint and drawLine into drawPoints and 00660 // drawLines, respectively. 00661 // <li> add circle, arc, rounded rectangle drawing primitives. 00662 // <li> implement rotated text perhaps at this level or maybe at the WorldCanvas level 00663 // <li> More testing of the drawing primitives. 00664 // <li> Correct bug related to clipwindow location when XCS (X coordinate syste) y 00665 // value is less than zero. 00666 // <li> Check function visibility for X11PixelCanvasColorTable 00667 // <li> WorldCanvas Coordinate routines. 00668 // <li> Check all HTML docs for problems. 00669 // </todo> 00670 // 00671 // The following is the todo list for the WorldCanvas and related classes 00672 // 00673 // <todo asof="1997/10/06"> 00674 // 00675 // <li> mapToColor and mapToColor3 functions that redirect to pixelCanvas 00676 // <li> decide what drawImage interface higher classes require, and implement 00677 // those in terms of the PixelCanvas interface. 00678 // <li> test multiple WorldCanvases on a single PixelCanvas. 00679 // <li> WCSplineResampleHandler class to handle bicubic interpolation of arrays ? 00680 // <li> WCFunctionalScaleHandler class to take a functional as a scale function ? 00681 // </todo> 00682 // 00683 // The following is the todo list for the application level classes: 00684 // <todo asof="1997/10/06"> 00685 // <li> Write simple display app with colormap editor. 00686 // <li> Demonstrate use of RonAndRenzo colormap implementation. 00687 // </todo> 00688 // 00689 // <hr> 00690 // 00691 // <b>The following section is intended for a programmer who wants to 00692 // improve the Display Library</b> 00693 // 00694 // <h3>Caching System Optimization</h3> 00695 // 00696 // An advanced optimization to the 00697 // <linkto class="PixelCanvas">PixelCanvas</linkto> 00698 // caching system would be to compact sequences 00699 // of drawing commands. This would mean that a sequence received 00700 // by the PixelCanvas would be transformed into a more efficient sequence 00701 // of drawing commands that produces the same result. Obviously, sequences 00702 // of the same commands can often be combined into a single command. 00703 // But consider for example a drawn raster image I followed by a set of 00704 // vectors V on top of the image. This sequence can be represented by 00705 // { I V }. 00706 // 00707 // We can partition V into 2 sets: Vin (contains vectors drawn inside the 00708 // image) and Vout (vectors that have portions drawn outside the image). 00709 // A new image I' can be created from I by drawing I onto a pixmap, then 00710 // painting the vectors Vin on top, and storing the resultant image I'. 00711 // 00712 // The cached sequence is then { I' Vout }, and I and V can be discarded 00713 // This will result in faster drawing times and reduced memory usage if 00714 // Vin has significant size because the vectors in Vin are not drawn explicitly. 00715 // 00716 // Similar results can be achieved with drawn text and points, so that some 00717 // sequence { I V P T } can be replaced with { I' Vout Pout Tout }. Also 00718 // overlapping images can be stored to avoid drawing the overlapping region 00719 // more than once. 00720 // 00721 // It is not clear whether this would be worthwhile to pursue, so it has not 00722 // been implemented. 00723 // 00724 // </synopsis> 00725 // 00726 // </module> 00727 // 00728 00729 00730 } //# NAMESPACE CASA - END 00731 00732 #endif 00733 00734 // ---- End of module Display ----