swarm-support
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Multiple Value2dDisplay's on a single Raster


From: Ken Cline
Subject: Re: Multiple Value2dDisplay's on a single Raster
Date: Tue, 21 Apr 1998 21:45:29 -0400 (EDT)

Since its now after 9 and I'm "off the clock"...

On Tue, 21 Apr 1998, Nelson Minar wrote:

> Can you just subclass Value2dDisplay and override the
> offending method?

This is exactly what I did to implement my contour lines
on top of the my elevation "gradient" display.

In my case, if the grid value was not part of the contour
line, then I used the standard "value / modFactor +
colorConstant" calculation to determine the appropriate
display color. Whether a grid value was part of the contour
line or not was determined by calculation, however, the same
strategy could be used to combine two (or more) grid data
sets.

I provided the code for my "Val2DDisplay" class in the
attached files. None of the code is documented so I put some
explanation about what I did below.

> I think it'd be pretty simple to do.

Yes, it was pretty easy to do, but, as you'll notice, I got
a little carried away. =:-) (I have a tendency to do this
when I'm spending my own time and etc. implementing features
like this.)

First, I have a library called "spatial" which contains
enhancements/additions to Swarm's "space" library.  The
classes in "spatial" are:
    BdGrid2D      Point2D   Val2DDisplay 
    GridMap       Point3D   Value2DLoader
    Obj2DDisplay            Value2DSaver

Not all of these are implemented and none are currently
documented [sigh]. I only mention the "spatial" library
because if you try to use Val2DDisplay it may complain
about needing one or more of the other classes and/or files.

Now, about the Val2DDisplay class...

1. Display modes
     The Val2DDisplay class has different display "modes"
or methods. I had originally plan to use Symbol objects
to set the display mode/method (ie `setDisplayState:') but
this wasn't very convenient for taking user input via
probes.  My solution was to add the `setDisplayMode:' method
which takes a char *.

      The code in `setDisplayMode:' appends the char *
argument, mode, onto the word "display".  For example, if
the argument was "Contour", then the variable displayMethodName
would equal "displayContour".  This method name is then
converted into a selector and, if the current object
`respondsTo' that selector, then I set the displayMode ivar
to that value.

      The idea is that any subclass of Val2DDisplay can add
a new display method, eg "displayFoo", and, without any
extra work, be able to switch back and forth between all the
display methods.  However, the new method must begin with
the word "display".  And, when you want to set the display
mode/method, you only use the end of the method name, eg
"Foo".  Similarily, with probes you'd only enter the word
"Foo".  (I didn't do the extra work to make this all case
insenitive, though.)

2. Color cache
      One of my major problems with the display rasters is
the refresh time.  As an attempt to speed things up a bit I
decided to cache the color values.  Since my elevation data
doesn't change once its been loaded into the grid, I figured
there was no reason to calculate the color values each time.
Instead, I write the color values to an array that has the
same xsize and ysize as the grid but whose elements are
sizeof unsigned char.

      The color cache did not make much of a difference,
unfortunately, so I never completed its implementation.  You
can turn on use of the cache by calling the `setCache:'
method and passing the "ARRAY_CACHE" macro as the argument.
However, there is no code there to free up the memory when
you turn off the cache and no code that updates the cache
when you change display modes.  (Not to mention the probable
implementation bugs, etc.)

      The real solution to (my) refresh speed problem is to
only update those raster pixels changed by agent movement,
but I haven't had a chance to try that out.  Note: with our
tcl/tk gui we draw agents with a series of X calls (this
predates the pixmap stuff) so the agent icons affect a whole
set of pixels and the size of that set would depend on the
current zoom factor... etc.


3. Overlay display
      Because it was difficult to interpret my elevation
data with my color gradient (ie there is no color bar on
the side showing how to map the color to the altitude
values), I decided to add an alternative, contour view.
(Note: I put the details about the contour calculations
below.)

      I wanted to show the contour lines both with a
monochromatic background (eg white) and on top of the
standard "gradient" view.  To accomplish this, I decided to
use a value of -1 as a flag since that's not a valid index
into a colormap. Then, to implement the `displayContourOverlay'
method, I just set contourBkgdColor to -1, call `displayContour'
and finally restore the original value of contourBkgdColor.


4. Left to do
      It would be really nice if the raster widgets also had
a color bar on the side with labeled values, ie a legend of
sorts.  It would also be really cool add a "toolbar" of
probes to the Raster so the user could change various
display variables.  Finally, I'd like to label my contour
lines, but this maybe a little more complex than just
drawing strings onto the raster widgets.


Finally, if you find any errors/bugs in my code, please let
my know. Also, if you have suggestions about better ways to
implement things, I'd appreciate hearing those ideas as
well.


Ken.



Contour display function:
------------------------
The contour display "bins" the data and colors the display
at each point depending on whether it on the border of 2
bins.
 
For example, suppose we have the data below:
 
         0    1    2    3  ...
     +---------------------------
   0 |  50   55   60   58  ...
   1 |  62   65   64   50  ...
   2 |  58   63   45   47  ...
   3 |  63   65   50   43  ...
   . |   .    .    .    .  ...
   . |   .    .    .    .  ...
   . |   .    .    .    .  ...
     |
 
And the contourModFactor = 5. Then the algorithm looks a 4
points on every loop (ie z00, z10, z01, z11) and calculates
the bin for each value (ie m00, m10, m01, m11, respectively)
by dividing by the contourModFactor.
 
After, dividing by contourModFactor we have:
 
         0    1   ...
     +----------------
   0 |  10   11   ...
   1 |  12   13   ...
   . |   .    .   ...
     |
 
Now, if all the values above were the same value (ie bin)
then point (1,1) would be given the contour background
color.  If there is any difference (ie different bins =>
boundary) then point (1,1) is given the contour line color.
Finally, if the difference between the other points and
point (1,1) is greater than 1, that is either:
   d1100 = difference between (0,0) and (1,1) > 1 or
   d1110 = difference between (1,0) and (1,1) > 1 or
   d1101 = difference between (0,1) and (1,1) > 1
 
then we crossed two (2) boundaries (ie 2 bins) so both
points are given the contour line color.
 
Sorry, I know I didn't explain it well... I hope you get the
idea.
 
NOTE: I've tried to make the code a little more efficient by
taking advantage of the "overlap" from one for-loop to the
next.



_________________________________________________________
Ken Cline                             address@hidden
SAIC                                 VOICE (410) 571-0413
Annapolis, MD                          FAX (301) 261-8427

Attachment: Val2DDisplay.tgz
Description: tar-ed & gzip-ed file


reply via email to

[Prev in Thread] Current Thread [Next in Thread]