casa
5.7.0-16
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
Groups
Pages
casa
code
display
Display.h
Go to the documentation of this file.
1
//# Display.h: Display module header file
2
//# Copyright (C) 1994,1995,1996,1997,1998,1999,2000
3
//# Associated Universities, Inc. Washington DC, USA.
4
//#
5
//# This library is free software; you can redistribute it and/or modify it
6
//# under the terms of the GNU Library General Public License as published by
7
//# the Free Software Foundation; either version 2 of the License, or (at your
8
//# option) any later version.
9
//#
10
//# This library is distributed in the hope that it will be useful, but WITHOUT
11
//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13
//# License for more details.
14
//#
15
//# You should have received a copy of the GNU Library General Public License
16
//# along with this library; if not, write to the Free Software Foundation,
17
//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18
//#
19
//# Correspondence concerning AIPS++ should be addressed as follows:
20
//# Internet email: aips2-request@nrao.edu.
21
//# Postal address: AIPS++ Project Office
22
//# National Radio Astronomy Observatory
23
//# 520 Edgemont Road
24
//# Charlottesville, VA 22903-2475 USA
25
//#
26
//# $Id$
27
28
#ifndef TRIALDISPLAY_DISPLAY_H
29
#define TRIALDISPLAY_DISPLAY_H
30
31
//#include <graphics/X11/X11Util.h>
32
#include <
display/Display/DisplayEnums.h
>
33
#include <
display/Display/PixelCanvasColorTable.h
>
34
#include <
display/Display/PixelCanvas.h
>
35
#include <
display/Display/WorldCanvas.h
>
36
37
// Go ahead and include X11 stuff for now
38
//#include <display/Display/X11PixelCanvasColorTable.h>
39
//#include <display/Display/X11PixelCanvas.h>
40
41
// Include Simple{World,Pixel}CanvasApp stuff
42
#include <display/Display/SimplePixelCanvasApp.h>
43
#include <display/Display/SimpleWorldCanvasApp.h>
44
45
namespace
casa {
//# NAMESPACE CASA - BEGIN
46
47
//
48
// <module>
49
//
50
// <summary>A module providing graphical display classes for use with AIPS++ </summary>
51
//
52
// <prerequisite>
53
// <li> <linkto class="casacore::Vector">casacore::Vector</linkto>
54
// <li> <linkto class="casacore::Matrix">casacore::Matrix</linkto>
55
// </prerequisite>
56
//
57
// <reviewed reviewer="None yet" date="yyyy/mm/dd" demos="">
58
// </reviewed>
59
//
60
// <etymology>
61
// Module provides classes for an Image Display Library
62
// </etymology>
63
//
64
// <synopsis> The purpose of the Display library is twofold: 1) to provide a
65
// set of tools for the AIPS++ programmer which make it easier to create
66
// drawing windows and use those drawing windows as output devices for
67
// graphical primitives, including images, and 2) to provide a set of higher-
68
// level classes to display datasets in a number of ways (images, contours, ...)
69
// as well as classes to help build an application that needs to display
70
// several datasets.
71
//
72
// A design goal is to have Display Library applications portable to
73
// another graphics system by augmenting the Library to provide an
74
// interface to that graphics system.
75
//
76
// <h1><center><Display Library Contents></center></h1>
77
//
78
// <ol>
79
// <li> <a href="#Overview">Display Library Overview</a>
80
// <li> <a href="#PixelCanvas">PixelCanvas</a>
81
// <ol>
82
// <li> <a href="#PCDrawingCommands">Drawing Commands</a>
83
// <li> <a href="#PCEvents">Event Handling</a>
84
// <li> <a href="#PCCaching">Caching Mechanism</a>
85
// <li> <a href="#PCColormaps">Colormap System</a>
86
// </ol>
87
// <li> <a href="#WorldCanvas">WorldCanvas</a>
88
// <ol>
89
// <li> <a href="#WCDrawingCommands">Drawing Commands</a>
90
// <li> <a href="#WCEvents">Event Handling</a>
91
// <li> <a href="#WCHandlers">Other Handlers</a>
92
// </ol>
93
// <li> <a href="#WorldCanvasHolder">WorldCanvasHolder</a>
94
// <li> <a href="#DisplayData">DisplayData</a>
95
// <li> <a href="#Zoomer">Zoomer</a>
96
// <li> <a href="#Animator">Animator</a>
97
// </ol>
98
//
99
// <hr>
100
//
101
// <h2><a name="Overview">Display Library Overview</a></h2>
102
//
103
// The Display library is a set of tools for the AIPS++ programmer which make
104
// it easier to create drawing windows and use those drawing windows as output
105
// devices for graphical primitives, including images. To some extent, the
106
// Display Library consists of two parts. One part is a set of device
107
// indepentent classes that give the basic functionality for data display. The
108
// classes of the first group are quite generic and can basically be used for
109
// any application that needs an interactive display window and these classes
110
// not tied to AIPS++ data sets or AIPS++ coordinate systems. They make only
111
// very few assumptions for what they will be used. The second part is more
112
// concerned with transforming data sets into objects that are understood by
113
// the first layer, as well as classes that should make it easier to build a
114
// full application that displays data. The classes of the second group can be
115
// quite data specific.
116
//
117
// The main classes from the first group are the PixelCanvas, the WorldCanvas
118
// and the ColorMap classes. The PixelCanvas conceptually corresponds to the
119
// window on the screen. It works only in 'screen' units, ie. screen pixel
120
// coordiantes and screen data values. The PixelCanvas is, to some extent, the
121
// interface between Aips++ and the display hardware and graphics environment
122
// (e.g. X11). The WorldCanvas is mostly an interface layer between the 'real
123
// world' and the PixelCanvas. Its main responsibility is to transform drawing
124
// instruction that are specified in world coordinates and world values to the
125
// corresponding instructions of the PixelCanvas specified in pixel
126
// coordinates and pixel values. The PixelCanvas and the WorldCanvas are
127
// intended to be relatively 'raw' devices. With this we mean that both
128
// classes have basically no knowledge of the classes that use these Canvases
129
// to display data. In effect, The PixelCanvas does not know what a
130
// WorldCanvas is. The reason to make the canvases relatively ignorant, is
131
// that by putting in as few assumptions as possible in the canvases, they
132
// (hopefully) can be used in a very wide range of applications. For example,
133
// it is quite easy to make a 2D colormap editor (an application that is quite
134
// different from e.g. displaying a contour map) based on the PixelCanvas or
135
// on the WorldCanvas. To achieve that only a few assumption have to be built
136
// in in the canvases, the canvases communicate to other classes via event
137
// handlers that these other classes have to register with the canvases. Also
138
// the PixelCanvas communicates with the WorldCanvas thourg such event
139
// handlers. For example, if the window corresponding to the Pixelcanvas is
140
// resized by the user, this generates a refresh event and the Pixelcanvas
141
// calls the refresh event handlers registered with the PixelCanvas. When a
142
// WorldCanvas is created, the first thing the WorldCanvas does is to install
143
// a number of event handlers on the PixelCanvas. This means that if e.g. the
144
// refresh event occurs on the PixelCanvas, the WorldCanvas is notified and
145
// takes the necessary action. This scheme of communication through event
146
// handlers is used throughout the Display Library. The classes that generate
147
// events do not have to know what classes consume these events, the only
148
// thing that is defined is the interface (and content) of the event. This
149
// means that one could build a class on top of the PixelCanvas that is quite
150
// different from the WorldCanvas.
151
//
152
// To keep the WorldCanvas as generic as possible, the coordinate system the
153
// WorldCanvas uses to transform from screen pixels to world coordinates and
154
// back is not stored in the WorldCnvas but is also defined through an event
155
// handler (a CoordinateHandler). If the WorldCanvas has to do a coordinate
156
// transformation, it asks the CoordinateHandler to do this. In many cases,
157
// this CoordinateHandler will use a standard Aips++ casacore::CoordinateSystem to do
158
// the transformation, but this is not a requirement, and the programmer can
159
// implement any tranformation required, as long as it satisfies the interface
160
// of the CoordinateHandler.
161
//
162
// The features of the first group include
163
//
164
// <ul>
165
// <li> Multi-layer programming library (PixelCanvas, WorldCanvas, Application)
166
// <li> PixelCanvas Interface which abstracts the underlying graphics library.
167
// <li> Colormap system allows applications to function independent of the
168
// number of available colors.
169
// <li> System color resources can be changed while running.
170
// <li> Drawing commands in world or pixel coordinates and values.
171
// <li> Events represented in world and pixel coordinates.
172
// </ul>
173
//
174
// The classes of the second group have a quite different purpose. They are
175
// much more concerned with building an application that needs to display one
176
// or more aips++ datasets in a number of ways.
177
//
178
// To make the link between the relatively generic display classes
179
// (PixelCanvas, WorldCanvas etc) and classes quite specific for displaying
180
// Aips++ datasets, an intermediate class is required. This class is called
181
// the WorldCanvasHolder. The main role of the WorldCanvasHolder is to catch
182
// the events that occur on a WorldCanvas and distribute these events to the
183
// data that is being displayed on the Worldcanvas. Another important role of
184
// the WorldCanvasHolder is that it is the class that is used to control what
185
// is actually displayed on the WorldCanvas. One important design requirement
186
// for the Display Library was that, from the programmer point of view, it
187
// should be easy to display more than one dataset in a window at the same
188
// time. A standard example is a contourmap on top of a greyscale image.
189
// Consequently, one can register more than one display object with the
190
// WorldCanvasHolder so that they are displayed at the same time.
191
//
192
// One important aspect that the WorldCanvasHolder takes care of is the
193
// sizeControl of the WorldCanvas. If a refresh event happens on the
194
// WorldCanvas, before invoking the refresh event handlers installed on the
195
// WorldCanvas, the WorldCanvas invokes a sizeControl event. The meaning of
196
// this event is to ask the object that draws on the WorldCanvas (e.g. the
197
// WorldCanvasHolder) to check if the state of the WorldCanvas is ok so that
198
// it can be drawn on, and if it is not ok, that the state of the WorldCanvas
199
// be modified. For example, if an image is drwan as a pseudeocolor image and
200
// the window (or WorldCanvas) is much larger that the data array, one wants
201
// to expand the data array so that it fills more or less the window. One way
202
// of doing this is to do this by pixelreplication. But this means that there
203
// are requirements on the size of the area that the WorldCanvas uses for
204
// drawing the image (it has to be a integer multiple of the size of the data
205
// array. This explains the name sizeControl). It is the responsibility of the
206
// objects that draw on the WorldCanvas, to get these size right. What in
207
// practice happens is that the WorldCanvasHolder asks the display objects to
208
// sort this out and set the correct size on the WorldCanvas. Once this is
209
// sorted out, the WorldCanvas is in the coreect state and things can be
210
// drawn. The name sizeControl is not entirely correct. The obvious use of
211
// this mechanism is as in the example described above, but the problem is
212
// more general: before display objects can draw on the WorldCanvas they have
213
// to be sure that the WorldCanvas is in the correct state and possibly they
214
// have to modify the attributes of the WorldCanvas. Because more than one
215
// display object can draw on the WorldCanvas, this has to be done before the
216
// actual drawing occurs (because the display objects do not know if there are
217
// more than one display objects drawing on the WorldCanvas).
218
//
219
// Another requirement for the Display Library was that no distinction should
220
// be made based on how data is displayed. For example, displaying an image as
221
// a pseudocolor image on the screen should, from the Display Library point of
222
// view, be the same operation as displaying that image as a contourmap. This
223
// means that the display object is quite an 'abstract' class. Display Objects
224
// in the Display Library are called DisplayData (or better: are derived from
225
// DisplayData). The role of the DisplayData is, using a certain algorithm, to
226
// transform data into one or more draw instructions for the WorldCanvas. An
227
// example is ImageDisplayData that takes an Aips++ dataset and display its
228
// contents as images, Another example would be ContourDisplayData that draws
229
// images as contourmaps. Also here, the communication to the DisplayData goes
230
// via calling event handlers. Depending on what happens (e.g. a refresh
231
// event, or a position event), the WorldCanvasHolder (who catches these
232
// events from the WorldCanvas), invokes member functions of the DisplayData
233
// registered with the WorldCanvasHolder (so to a large extent, a DisplayData
234
// is an event handler on the WorldCanvasHolder). For example, if a refresh
235
// event happens, the WorldCanvasHolder will ask the DisplayData to draw what
236
// they should draw. If a programmer wants to implement a new way of
237
// displaying data, what this programmer has to do is to implement a new class
238
// derived from DisplayData that computes whatever it has to compute (say a
239
// volume rendering of a datacube) and transform this into draw instructions
240
// for the WorldCanvas (in this example, just call WorldCanvas.drawImage() on
241
// the result of the volume rendering). A class derived from DisplayData does
242
// not need to have an Aips++ dataset, but one could for example image a
243
// DisplayData class that reads positions from a catalog and plots these
244
// positions on the WorldCanvas.
245
//
246
// Because everything in the Display Library is event driven, it is also easy
247
// to make applications that require more than one display window. The
248
// programmer only has to decide how to link the various windows by installng
249
// the appropriate event handlers on the various classes. An example of how
250
// this can be done is the Zoomer class. This class is a high-level class that
251
// catches position events on the WorldCanvases (possibly more than one) that
252
// are registered with the Zoomer. If the right event happens on one of the
253
// WorldCanvases (say, the user is rubberbanding a rectangle), the Zoomer sets
254
// the correct attributes on all the WorldCanvases registered with the Zoomer
255
// (meaning: it defines the area to which should be zoomed in) and invokes a
256
// refresh event on all these WorldCanvases. This means that all the
257
// WorldCanvases will zoom in synch.
258
//
259
// Another design requirement of the Display Library was that it should be
260
// easy to display movies, and the DisplayData are build with sequences in
261
// mind (as is clear from their interface). The programmer is free to define
262
// what a sequence really means, but it is probably best to keep the structure
263
// of the sequence in a DisplayData logical to at least some extent. But there
264
// is no real requirement on the structure of the sequence. Movies can be
265
// controlled using the Animator class. The easy way is to use indices, but
266
// there is a generic way of defining movies using restrictions (see later
267
// what these mean). So a sequence does not have to correspond to a 'physical'
268
// sequence in one datastructure (channels in a cube for example), but can be
269
// made of representations of different datasets (e.g. blinking), or more
270
// exotic combinations of different datasets displayed in different form
271
// (e.g. blink between a greyscale and a contourmap, if such a thing would be
272
// useful). This system is very flexible and there are no real limits to what
273
// a movie really means.
274
//
275
// An important concept in the Display Library is that of Attributes (and
276
// their use as restrictions). Attributes are name-value pairs. Many classes
277
// of the Display Library have a buffer where they can store these Attributes.
278
// They can be used for various things (see AttributeBuffer for a number of
279
// examples). One applications is that a uniform userinterface can be defined
280
// for changing attributes of a class (meaning internal members), but since
281
// Attributes can have an arbitrary name, they can be used to place (almost)
282
// any kind of information on classes <em> at run time</em>. This provides a
283
// mechanism of distributing information in a display aplication, while at
284
// compile time it is not yet defined what that information is (name, type,
285
// etc).
286
//
287
// An important application of Attributes is their use as
288
// <em>restrictions</em>: they are used to select which data is actually
289
// displayed. DisplayData classes, like ImageDisplayData, are supposed to have
290
// defined, for each distinct representation that they can draw, one or more
291
// Attributes, specifically defined to select what data is displayed. These
292
// Attributes are in a separate (or several separate) AttributeBuffer, called
293
// the <em>restriction buffer</em>. Also the WorldCanvasHolder has such a
294
// restriction buffer whose content should be controlled by the application
295
// programmer. If a refresh happens, the WorldCanvasHolder, after the
296
// sizeControl step, asks each DisplayData that is registered with the
297
// WorldCanvasHolder to draw itself, by calling the refreshEH() member of each
298
// DisplayData. The first thing that a DisplayData should do it to see if the
299
// restrictions that are placed on the WorldCanvasHolder are compatible with
300
// this DisplayData and/or check with which element of the DisplayData the
301
// restriction buffer WorldCanvasHolder is compatible. If the DisplayData has
302
// compatible data, it should draw this data. An example may make this process
303
// clearer. An ImageDisplayData is a class derived from DisplayData that
304
// displays the 2D slices from a n-dimensional dataset on a canvas (for
305
// example the channels from a datacube). An ImageDisplayData has two general
306
// restrictions (meaning they apply to all channels): the names of the axes
307
// ("xAxisName" = "Ra" and "yAxisName" = "Dec"). Since an ImageDisplayData
308
// (possibly) consists of a number of channels, additional restrictions exist,
309
// but these have a different value for each element (ie. channel). In the
310
// case of an ImageDisplayData, each 2D subset has defined "zIndex" and
311
// "zValue", the first has the value of the pixelcoordinate of the 2D image
312
// (in our example channel number), the second has the value of the
313
// WorldCoordinate of centre of the 2D image (in our example the velocity of
314
// the channel). So to display a channel, a programmer has to set 3
315
// restrictions on the WorldCanvasHolder: "xAxisName", "yAxisName" to select
316
// channels from a datacube and set these to "Ra" and "Dec" (or whatever is in
317
// the header of the data), plus a restriction to select the actual channel,
318
// e.g. set "zIndex" to 20 to select channel 20, or "zValue" to 1200.0, to
319
// select the channel corresponding to velocity 1200.0. To display a position
320
// velocity image, one would have to specify e.g. "xAxisName" = "Dec" and
321
// "yAxisName" = "Velocity" and set "zValue" to 5.23443311 (the Ra of the
322
// slice you want to look at).
323
//
324
// To determine if restrictionbuffers match, one can simply use the member
325
// matches() of an AttributeBuffer. The logic of matching restrictions is
326
// perhaps a bit distorted: restrictions (or Attributes in general) of
327
// different names <em> always match</em>. So if a DisplayData has a
328
// restriction called "A" and the WorldCanvasHolder specifies "B", the
329
// DisplayData should draw itself. Restrictions (and Attributes) can have some
330
// tolerance. In our example we could have specified "zValue" to be 1200.0,
331
// plus or minus 5.0. This obviously can be used e.g. to match the channels of
332
// two data cubes that are on a different velocity grid. The Animator class,
333
// who can be used to make movies, completely relies on this restriction
334
// mechanism.
335
//
336
//
337
//
338
// <hr>
339
//
340
// <h2><a name="PixelCanvas">The PixelCanvas</a></h2>
341
//
342
// The PixelCanvas display library defines an interface to an underlying
343
// 2D graphics library.
344
//
345
// The design of the PixelCanvas emphasizes the following features:
346
//
347
// <ul>
348
// <li> Straightforward drawing interface using simple Aips++ array types
349
// <li> Enhanced event handling - Event classes can be derived from to
350
// add extra functionality.
351
// <li> Advanced caching system - User can create sequences of drawing commands
352
// for later recall. Sequences can be compacted and stored into
353
// native structures for increased drawing performance.
354
// <li> Ability to register and use several colormaps in the same window at
355
// the same time.
356
// <li> Minimize the dependency on the underlying graphics system, in
357
// this case, X11.
358
// </ul>
359
//
360
//
361
// <h3><a name="PCDrawingCommands">PixelCanvas Drawing Commands</a></h3>
362
//
363
// PixelCanvas drawing commands accept simple AIPS++ objects. Presently the
364
// drawing commands accept points as casacore::Vector<t>'s, where t can be
365
// any scalar type but Bool. casacore::Bool images are not supported because a Bool
366
// cannot represent a color index. casacore::Complex values are not supported because
367
// there are many ways of creating a single scalar value from complex
368
// values.
369
//
370
//
371
// <h3><a name="PCEvents">PixelCanvas Event Handling</a></h3>
372
//
373
// There are 3 kinds of events the PixelCanvas reports
374
//
375
// <ol>
376
// <li> refresh event - sent when the canvas must be redrawn.
377
// <li> position event - sent when a button or key is pressed.
378
// <li> motion event - sent when the mouse moves over the cursor.
379
// </ol>
380
//
381
// Applications handle
382
// <linkto class=PixelCanvas>PixelCanvas</linkto> events by creating
383
// <linkto class=PixelCanvas>PixelCanvas</linkto> event handlers
384
// that must be derived from the appropriate event class, either
385
// <linkto class=PCRefreshEH>PCRefreshEH</linkto>,
386
// <linkto class=PCPositionEH>PCPositionEH</linkto>, or
387
// <linkto class=PCMotionEH>PCMotionEH</linkto>. The () operator
388
// must be overridden and implemented by responding to the
389
// information contained in the
390
// <linkto class=PCRefreshEvent>PCRefreshEvent</linkto>,
391
// <linkto class=PCPositionEvent>PCPositionEvent</linkto>, or
392
// <linkto class=PCMotionEvent>PCMotionEvent</linkto>, as appropriate.
393
//
394
//
395
// <h3><a name="PCCaching">PixelCanvas Caching Mechanism</a></h3>
396
//
397
// There is a system for creating sequences of commands. It works
398
// be turning on caching, performing drawing commands, then shutting
399
// it off. An id is returned to the user to recall the stored
400
// sequence. This gives the user control over what is to be cached
401
// while still abstracting the business of caching.
402
//
403
// The cache system improves drawing speed by storing drawing data
404
// in native library formats.
405
//
406
// casacore::Data stored in native formats means that, for the X11PixelCanvas,
407
//
408
// <ul>
409
// <li> images are stored in terms of pixels as XImages,
410
// <li> coordinate positions are stored how X likes them (upper left is 0,0),
411
// <li> lines are stored as XLines or XSegments, as appropriate
412
// <li> Points are stored as XPoints.
413
// <li> Pixmap Text is stored as drawing strings
414
// <li> Stroked Text is stored as XSegments or XLines
415
// </ul>
416
//
417
// It is the responsibility of the user to rebuild display lists
418
// when necessary. Normally this means when the canvas changes
419
// size or colormap distribution (if colormaps are in use).
420
//
421
//
422
// <h3><a name="PCColormaps">PixelCanvas Colormap System</a></h3>
423
//
424
// The PixelCanvas colormap system design was one of the most difficult
425
// design problems we faced in building this system. The design goals
426
// were as follows:
427
//
428
// <ol>
429
// <li> Wanted to be able to pretend we had multiple simultaneous
430
// colormaps available in some display window.
431
// <li> Wanted to allow for but not demand that multiple windows
432
// share the same hardware colormap.
433
// <li> Wanted to distribute the same colormap to different windows
434
// potentially displaying on different terminals.
435
// <li> Wanted to allow for customizing the colormaps, and allow for
436
// data-dependent colormaps.
437
// <li> Wanted to be able to resize the available colormap while
438
// a Display library application was running.
439
// </ol>
440
//
441
// The constraints above have driven us to the following scheme:
442
//
443
// <ol>
444
// <li> Create something called a
445
// <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>
446
// and let it define a table of available colors for one or more
447
// <linkto class="PixelCanvas">PixelCanvas</linkto>es and be responsible
448
// for interfacing to the underlying graphics system's color allocation
449
// facilities. Through the
450
// <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>
451
// one can abstract away the underlying graphic library's tedious and
452
// cumbersome constructs and functions required to manage color resources
453
// and visuals and provide a high-level interface based on concepts
454
// that are better understood. This interface is implemented as the
455
// constructors for the classes derived from the
456
// <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>
457
// class.
458
//
459
// <li> Define a <linkto class=Colormap>Colormap</linkto> to mean not a
460
// table of colors, but rather a function that takes a floating-point
461
// parameter in [0.0,1.0] and returns an RGB triple. This function can
462
// then be used to fill some arbitrary number of consecutive colorcells.
463
// Allow for <linkto class=Colormap>Colormap</linkto>s to be of a fixed
464
// size if needed (then they are called 'rigid')
465
// and design them for derivation so custom colormaps can be created
466
// and used in this system.
467
//
468
// <li> Define a <linkto class=ColormapManager>ColormapManager</linkto> to be
469
// responsible for dynamically partitioning its
470
// <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>
471
// into chunks, one chunk for each registered
472
// <linkto class=Colormap>Colormap</linkto>, allowing for rigid
473
// <linkto class=Colormap>Colormap</linkto>s (that must be for some reason
474
// of a particular size) and weights to give greater color resolution
475
// to certain maps. Make it responsible for filling in the color based
476
// on its distribution of <linkto class=Colormap>Colormap</linkto>s
477
// in the <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>.
478
//
479
// <li> Allow for <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>s
480
// to be shared by more than one <linkto class="PixelCanvas">PixelCanvas</linkto>,
481
// and allow <linkto class="PixelCanvas">PixelCanvas</linkto>es to share
482
// <linkto class=Colormap>Colormap</linkto>s.
483
//
484
// <li> Try to abstract away all this mess by placing gateways to necessary
485
// functionality in the <linkto class="PixelCanvas">PixelCanvas</linkto>
486
// itself. For example images are drawn on the
487
// <linkto class="PixelCanvas">PixelCanvas</linkto> through the following
488
// process:
489
//
490
// <ol>
491
// <li> register a <linkto class=Colormap>Colormap</linkto> with the
492
// <linkto class="PixelCanvas">PixelCanvas</linkto> (needed only once).
493
// <li> set the active colormap to the one used in step 1.
494
// <li> create an image whose values range from 0 to N-1, where N is the size
495
// of the active colormap
496
// (<linkto class="PixelCanvas">PixelCanvas</linkto>::getColormapSize()).
497
// <li> call <linkto class="PixelCanvas">PixelCanvas</linkto>::mapToColor().
498
// to convert to color values.
499
// <li> call <linkto class="PixelCanvas">PixelCanvas</linkto>drawImage()
500
// with the casacore::Matrix of color values
501
// </ol>
502
//
503
// The color image can be reused as long as the distribution of colors
504
// on the
505
// <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>
506
// doesn't change. Any such change will trigger a refresh event with the
507
// reason Display::ColorTableChange on the affected
508
// <linkto class="PixelCanvas">PixelCanvas</linkto>.
509
// This process can also be used to draw other primitives that each have
510
// a value associated with it.
511
// Several colormaps can be switched between by setting the active
512
// colormap and querying the range, and using the mapToColor function.
513
//
514
// <li> Implement a function that resizes the
515
// <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>,
516
// forcing a redistribution of colormaps on affected
517
// <linkto class="PixelCanvas">PixelCanvas</linkto>es followed by a
518
// refresh event. This ultimately causes a reallocation of writable
519
// color cells on the underlying graphics library and can be
520
// used to increase or decrease the number of color cells available to
521
// the <linkto class="PixelCanvasColorTable">PixelCanvasColorTable</linkto>
522
// and hence to the application. This mechanism can be used to recover
523
// allocated color cells from the system map released by other applications
524
// when they exit, or to balance color resources between two or more
525
// applications.
526
//
527
// </ol>
528
//
529
// <hr>
530
//
531
// <h2><a name="WorldCanvas">The WorldCanvas</a></h2>
532
//
533
// The <linkto class=WorldCanvas>WorldCanvas</linkto> is intended to
534
// serve as a world-coordinate plotting canvas
535
//
536
//
537
// <h3><a name="WCDrawingCommands">WorldCanvas DrawingCommands</a></h3>
538
//
539
// The <linkto class=WorldCanvas>WorldCanvas</linkto> drawing commands
540
// expect to be given world coordinate values for position information.
541
//
542
//
543
// <h3><a name="WCEvents">WorldCanvas Event Handling</a></h3>
544
//
545
// The <linkto class=WorldCanvas>WorldCanvas</linkto> event handling
546
// is similar to the <linkto class=PixelCanvas>PixelCanvas</linkto>
547
// event handling, but the <linkto class=WorldCanvas>WorldCanvas</linkto>
548
// events contain extra information which includes the world coordinate
549
// and linear coordinate position of the mouse pointer. The same
550
// basic three events are available:
551
//
552
// <ol>
553
// <li> refresh event - sent when the canvas must be redrawn.
554
// <li> position event - sent when a button or key is pressed.
555
// <li> motion event - sent when the mouse moves over the cursor.
556
// </ol>
557
//
558
// Applications handle
559
// <linkto class=WorldCanvas>WorldCanvas</linkto> events by creating
560
// <linkto class=WorldCanvas>WorldCanvas</linkto> event handlers
561
// that must be derived from the appropriate event class, either
562
// <linkto class=WCRefreshEH>WCRefreshEH</linkto>,
563
// <linkto class=WCPositionEH>WCPositionEH</linkto>, or
564
// <linkto class=WCMotionEH>WCMotionEH</linkto>. The () operator
565
// must be overridden and implemented by responding to the
566
// information contained in the
567
// <linkto class=WCRefreshEvent>WCRefreshEvent</linkto>,
568
// <linkto class=WCPositionEvent>WCPositionEvent</linkto>, or
569
// <linkto class=WCMotionEvent>WCMotionEvent</linkto>, as appropriate.
570
//
571
//
572
// <h3><a name="WCHandlers">Other WorldCanvas Handlers</a></h3>
573
//
574
// Other handlers can be registered with the WorldCanvas to customize:
575
// <ul>
576
// <li> World casacore::Coordinate transformations
577
// <li> Linear resampling algorithm
578
// <li> casacore::Data scaling methods
579
// <li> Size control function
580
// </ul>
581
//
582
//
583
// <h2><a name="WorldCanvasHolder">The WorldCanvasHolder</a></h2>
584
//
585
// The WorldCanvasHolder is a user of a WorldCanvas. It installs handlers on
586
// the WorldCanvas for each event a WorldCanvas can generate. The main role
587
// of the WorldCanvasHolder is to allow to have more than one DisplayData
588
// object draw on a WorldCanvas (e.g contours on top of an image). A number
589
// of DisplayDatas can be registered with a WorldCanvasHolder, and the
590
// WorldCanvasHolder passes WorldCanvas events to these DisplayData.
591
// To control what is displayed on a WorldCanvas, the programmer can put
592
// restrictions on a WorldCanvasHolder. Only those DisplayData do actually
593
// draw whose restrictions match those of the WorldCanvasHolder. See the
594
// example given above, or have a look at the doc of the Animator.
595
//
596
// <h2><a name="DisplayData">The DisplayData Interface</a></h2>
597
//
598
// A DisplayData is the class that transforms data (in whatever form: an
599
// image, a cube, a catalog or whatever) into drawing instructions for the
600
// WorldCanvas. A DisplayData is the 'workhorse' of the display libary: here
601
// is defined in what way on can represent data. If one want to add a new way
602
// of displaying data to aips++, they only thing that has to be done is to
603
// write a new class, derived from DisplayData, that computes this new
604
// representation and draws it. For example, if one would want to add volume
605
// rendering to aips++, one would have to write a class that computes this
606
// volume rendering (e.g. using some hot-gas algorithm), and draw the result
607
// of this on a WorldCanvas (ie. simply WorldCanvas.drawImage() on the
608
// result). DisplayDatas are registered witha WorldCanvasHolder and the
609
// restriction mechanism is used to select what is being
610
// displayed. DisplayDatas are also responsible for defining the
611
// WorldCoordinate system of the WorldCanvas (they have an interface that can
612
// be called (indirectly) by the WorldCanvas to do the transformations), as
613
// wel las they have to insure that the state of the WorldCanvas is ok (the
614
// sizeControl, see above). An example of a DisplayData is the
615
// ImageDisplayData class, that draws pseudocolor images from a data set.
616
//
617
// <h2><a name="Zoomer">The Zoomer</a></h2>
618
//
619
// Zooming is done by setying the linear coordinates of the WorldCanvas to
620
// define the zoom area (using a set function of the WorldCanvas) and force a
621
// refresh of the WorldCanvas. The Zoomer class defines the userinterface for
622
// zooming. One can register one (or more) WorldCanvas with a Zoomer. This
623
// Zoomer installs a position event handler on the WorldCanvas that listens
624
// to certain key- and mouse events. The Zoomer defines a default
625
// userinterface, but this can be re-defined. A Zoomer can also handle more
626
// than one WorldCanvas, so it is easy to let different WorldCanvases zoom in synch.
627
//
628
// <h2><a name="Animator">The Animator</a></h2>
629
//
630
// The role of the Animator is to give an easy way of controling what is
631
// displayed on one or more WorldCanvases. By specifying how an Animator
632
// controls what is displayed (by using indices, world coordinates or
633
// restrictions), the Animator sets the necessary restrictions on the
634
// WorldCanvasHolders that are registered with the Animator, and forces a
635
// refresh on all of them. All WorldCanvasHolder registered on an Animator
636
// move in synch.
637
//
638
//
639
//
640
641
// <hr>
642
//
643
// <motivation>
644
// Need to provide some usefull tools to assist in developing graphical
645
// C++ applications, addressing the problems encountered in trying to
646
// use other graphical libraries.
647
// </motivation>
648
//
649
// <hr>
650
// This section is intended as information about what tasks remain to be
651
// accomplished for the Display library.
652
//
653
// The following list illustrates work remaining at the PixelCanvas level:
654
//
655
// <todo asof="1997/10/06">
656
// <li> <b>PixelCanvas</b>: change/add PixelCanvas interface to use Matrices for multiple
657
// vector graphic primitives, and use those interfaces at the
658
// WorldCanvas level.
659
// <li> compact sequences of drawPoint and drawLine into drawPoints and
660
// drawLines, respectively.
661
// <li> add circle, arc, rounded rectangle drawing primitives.
662
// <li> implement rotated text perhaps at this level or maybe at the WorldCanvas level
663
// <li> More testing of the drawing primitives.
664
// <li> Correct bug related to clipwindow location when XCS (X coordinate syste) y
665
// value is less than zero.
666
// <li> Check function visibility for X11PixelCanvasColorTable
667
// <li> WorldCanvas casacore::Coordinate routines.
668
// <li> Check all HTML docs for problems.
669
// </todo>
670
//
671
// The following is the todo list for the WorldCanvas and related classes
672
//
673
// <todo asof="1997/10/06">
674
//
675
// <li> mapToColor and mapToColor3 functions that redirect to pixelCanvas
676
// <li> decide what drawImage interface higher classes require, and implement
677
// those in terms of the PixelCanvas interface.
678
// <li> test multiple WorldCanvases on a single PixelCanvas.
679
// <li> WCSplineResampleHandler class to handle bicubic interpolation of arrays ?
680
// <li> WCFunctionalScaleHandler class to take a functional as a scale function ?
681
// </todo>
682
//
683
// The following is the todo list for the application level classes:
684
// <todo asof="1997/10/06">
685
// <li> Write simple display app with colormap editor.
686
// <li> Demonstrate use of RonAndRenzo colormap implementation.
687
// </todo>
688
//
689
// <hr>
690
//
691
// <b>The following section is intended for a programmer who wants to
692
// improve the Display Library</b>
693
//
694
// <h3>Caching System Optimization</h3>
695
//
696
// An advanced optimization to the
697
// <linkto class="PixelCanvas">PixelCanvas</linkto>
698
// caching system would be to compact sequences
699
// of drawing commands. This would mean that a sequence received
700
// by the PixelCanvas would be transformed into a more efficient sequence
701
// of drawing commands that produces the same result. Obviously, sequences
702
// of the same commands can often be combined into a single command.
703
// But consider for example a drawn raster image I followed by a set of
704
// vectors V on top of the image. This sequence can be represented by
705
// { I V }.
706
//
707
// We can partition V into 2 sets: Vin (contains vectors drawn inside the
708
// image) and Vout (vectors that have portions drawn outside the image).
709
// A new image I' can be created from I by drawing I onto a pixmap, then
710
// painting the vectors Vin on top, and storing the resultant image I'.
711
//
712
// The cached sequence is then { I' Vout }, and I and V can be discarded
713
// This will result in faster drawing times and reduced memory usage if
714
// Vin has significant size because the vectors in Vin are not drawn explicitly.
715
//
716
// Similar results can be achieved with drawn text and points, so that some
717
// sequence { I V P T } can be replaced with { I' Vout Pout Tout }. Also
718
// overlapping images can be stored to avoid drawing the overlapping region
719
// more than once.
720
//
721
// It is not clear whether this would be worthwhile to pursue, so it has not
722
// been implemented.
723
//
724
// </synopsis>
725
//
726
// </module>
727
//
728
729
730
}
//# NAMESPACE CASA - END
731
732
#endif
733
734
// ---- End of module Display ----
PixelCanvasColorTable.h
WorldCanvas.h
PixelCanvas.h
DisplayEnums.h
Generated on Sun Sep 1 2019 23:32:29 for casa by
1.8.5