[comp.object] Should objects draw themselves?

pcb@gator.cacs.usl.edu (Peter C. Bahrs) (08/09/90)

 >Article 1064 of comp.object:
 >...
 >QUESTION: Should a `Shape' be able to `draw' itself?
 >
 >The usual answer is ABSOLUTELY.  I have to totally agree, since adding a
 >new Shape (Hexagon, for example) only requires adding code rather than
 >changing existing code (as would be required if there were a global `draw'
 >function).  This is the usual ``don't operate on objects; instead enable
 >the object to provide services for you''.
 >
 >However: what if I add a new terminal type?  Or what if I want a textual
 >...
 >The best I've come up with is this:
 >
 >	    GraphicalShape     TextualShape   <-- One per `view'
 >	                 \     /
 >	                  \   /
 >	                  Shape
 >	                 /  |  \
 >	                /   |   \
 >	               /    |    \
 >	         Square   Circle  Hexagon     <-- One per concrete Shape
 >
 >	class GraphicalShape { public: void graphical_draw() = 0; };
 >	class TextualShape   { public: void textual_draw()   = 0; };
 >	class Shape : public GraphicalShape, public TextualShape { };
 >

I agree somewhat, but consider the following.  What happens when these
objects have to draw themselves in relation to other objects, i.e. if
objects have priorities (such as in a graphics system where farther objects
are drawn first 'painters algorithm')?  

This is compicated when user defined objects contain the drawable primitives.
Suppose object A has a list of squares and circles and only N of the should
be drawn in state S.  Now there are multiple objects like A and all of them
need theirselves represented in some relation R to each other.

I guess some procedure sifts through all objects to be drawn, queries each
object by sending them some kind of 'where are you so I can compare you
to others and determine if you should really draw yourself now' message.

The other technique is is to pass the drawing area to each object and
since each object must be made of primitive(s) that can draw themselves,
then this object can draw itself.  

What about 3D drawables...3d- to 2d conversion, perspective transformation?


/*----------- Thanks in advance... --------------------------------------+
| Peter C. Bahrs                                                         |
| The USL-NASA Project                                                   |
| Center For Advanced Computer Studies      INET: pcb@gator.cacs.usl.edu |
| 2 Rex Street                                                           |
| University of Southwestern Louisiana      ...!uunet!dalsqnt!gator!pcb  | 
| Lafayette, LA 70504                                                    |
+-----------------------------------------------------------------------*/

johnson@m.cs.uiuc.edu (08/09/90)

>>QUESTION: Should a `Shape' be able to `draw' itself?
>>The usual answer is ABSOLUTELY. ...
>>However: what if I add a new terminal type?  Or what if I want a textual
>>...

>I agree somewhat, but consider the following.  What happens when these
>objects have to draw themselves in relation to other objects, i.e. if
>objects have priorities (such as in a graphics system where farther objects
>are drawn first 'painters algorithm')?  

Double-dispatching solves the problem of different terminal types
nicely.  See Ingall's paper in OOPSLA'86, or my paper in the March/April
issue of JOOP this year.

When life gets even more complicated, I fall back on the "mechanism, not
policy" advice that was given earlier.  Complex behavior requires complex 
designs, and 3D graphics requires other objects to represent things
like perspective.

If you want to see how to handle 2D graphics well, you might look at

[VL89] John M. Vlissides and Mark A. Linton, "Unidraw: A Framework for
Building Domain-Specific Graphical Editors", Proceedings of the ACM User
Interface Software and Technologies '89 Conference, November 1989.

Has anybody seen any papers on object-oriented designs for 3D graphics?
In my opinion, papers that describe particular designs are very important
and there should be more of them.

Ralph Johnson - University of Illinois at Urbana-Champaign

kim@spock (Kim Letkeman) (08/09/90)

In article <12873@rouge.usl.edu>, pcb@gator.cacs.usl.edu (Peter C. Bahrs) writes:
| I agree somewhat, but consider the following.  What happens when these
| objects have to draw themselves in relation to other objects, i.e. if
| objects have priorities (such as in a graphics system where farther objects
| are drawn first 'painters algorithm')?  
| 
| This is compicated when user defined objects contain the drawable primitives.
| Suppose object A has a list of squares and circles and only N of the should
| be drawn in state S.  Now there are multiple objects like A and all of them
| need theirselves represented in some relation R to each other.
| 
| I guess some procedure sifts through all objects to be drawn, queries each
| object by sending them some kind of 'where are you so I can compare you
| to others and determine if you should really draw yourself now' message.
| 
| The other technique is is to pass the drawing area to each object and
| since each object must be made of primitive(s) that can draw themselves,
| then this object can draw itself.  
| 
| What about 3D drawables...3d- to 2d conversion, perspective transformation?

I feel that it is much too difficult to build this much understanding
into the object itself. (Including the understanding of graphical
versus textual representation as described in the posting to which the
above is a response.) If an object is a square, then it should be able
to display itself without thinking about the world in which it happens
to exist at this time. 

It is, in fact, the rest of the world (i.e. other objects such as the
world, the view port, the physical device in use ...) that must be
able to interpret the displayed object and present it correctly.

This requires that an intermediate graphical language be used that can
render any object to the best level of detail required. The object may
then be concerned with displaying itself in this known language and
should never have to change. As well, additional (new) objects will
have no effect on existing objects.

Other objects that are stimulated by these graphical commands when an
object is drawing itself would render it by whatever rules are in
place at the time of drawing. (For example, a text window object might
just display "4x4 yellow square at 4,21,5" where a graphical display
window might render the same visually.)

I am really impressed by the separation of function that can be
achieved with OOP. But trying to teach every object about every other
part of the system creates more problems than it solves.
-- 
Kim Letkeman    mitel!spock!kim@uunet.uu.net

brucec@phoebus.phoebus.labs.tek.com (Bruce Cohen;;50-662;LP=A;) (08/17/90)

In article <77500047@m.cs.uiuc.edu> johnson@m.cs.uiuc.edu writes:
> 
> When life gets even more complicated, I fall back on the "mechanism, not
> policy" advice that was given earlier.  Complex behavior requires complex 
> designs, and 3D graphics requires other objects to represent things
> like perspective.

I'd go even farther than this in separating the objects used in graphics,
especially 3D.  First off, it's very useful to distinguish between
"physical" objects, "geometric" objects and "graphic" objects.

Physical objects have attributes like mass, surface reflectivity,
elasticity, etc, and they know how to react to forces applied to them and
light shown on them.  They used in physically-based models as the elements
of complex mechanically-correct mechanisms.

Geometric objects have attributes like shape and size, and they know how to
group together and modify each other (for instance Constructive Solid
Geometry objects or differential manifolds).  They are used to model
geometric relations, and as the parts from which physical objects derive
their notions of shape and size.

Graphic objects have attributes like color, and they know how to display
themselves.  They are used to build scenes which can be viewed.  They are
the objects which geometric objects use for display.

Example: say I have a geometric object which models a rubber ball.  It has
a certain mass, represented by a scalar, and a certain elasticity,
represented (in general) by a tensor field.  The ball has a geometric
object which it uses when it is concerned with shape and size.  It could if
it wanted to, make that object a sphere in the relaxed state, and change to
a more general ellipsoid only if stressed.  This provides some decoupling
between the physical model and the geometry used to model it.  Now the
physical object is asked to draw itself.  It passes the request on to the
geometric object, which has a set of of graphic objects it can tell to
draw.  It might have one graphic object: a sphere, or several: a collection
of flat facets.  These graphic objects in turn might have different ways to
draw themselves depending on the type of display, etc.

Now I agree, I've put some policy in the graphic objects, which sounds bad.
But on the other hand, I've insulated the physical model programmer from
the graphics completely.  In a practical system, the graphic objects would
be provided as low-level system utilities, to be reused by any application
programmer.

While I haven't seen any papers on this sort of thing, I expect to see some
in the near future; I know of several people who've looked into it in the
past couple of years.
---------------------------------------------------------------------------
NOTE: USE THIS ADDRESS TO REPLY, REPLY-TO IN HEADER MAY BE BROKEN!
Bruce Cohen, Computer Research Lab        email: brucec@tekcrl.labs.tek.com
Tektronix Laboratories, Tektronix, Inc.                phone: (503)627-5241
M/S 50-662, P.O. Box 500, Beaverton, OR  97077

--
---------------------------------------------------------------------------
NOTE: USE THIS ADDRESS TO REPLY, REPLY-TO IN HEADER MAY BE BROKEN!
Bruce Cohen, Computer Research Lab        email: brucec@tekcrl.labs.tek.com
Tektronix Laboratories, Tektronix, Inc.                phone: (503)627-5241
M/S 50-662, P.O. Box 500, Beaverton, OR  97077