Number: 1827

Date: 13-Aug-84 12':03':20

Submitter: Roach

Source: Roach

Subject: DRAWLINE inadequacies

Lisp Version: 10-Aug-84 18':02':13

Description: The DRAWLINE algorithm lacks xy symmetry, is discontinuous, and is too hard to use for detailed work.'
'
                       INADEQUACY #1'
'
    First, I think certain xy symmetries should be built into DRAWLINE''s algorithm.  The shape of any non-horizontal, non-vertical vector can be determined via reflection principles from a vector with direction between 0 and 45 degrees. '
(1)  (DRAWLINE Y1 X1 Y2 X2 ...)'
should be the reflection of'
     (DRAWLINE X1 Y1 X2 Y2 ...)'
about x=y.'
(2)  (DRAWLINE (IMINUS X1) Y1 (IMINUS X2) Y2 ...)'
should be the reflection of'
     (DRAWLINE X1 Y1 X2 Y2 ...)'
about the x=0.'
(3)  (DRAWLINE X1 (IMINUS Y1) X2 (IMINUS Y2) ...)'
should be the reflection of'
     (DRAWLINE X1 Y1 X2 Y2 ...)'
about the y=0.'
     The existing algorithm appears to only have (1) and (3).  We see for example that'
     (DRAWLINE 0 0 2 4 ...) and'
     (DRAWLINE 0 0 -2 4 ...)'
produce bitmaps'
     ..X     X..'
     ..X     .X.'
     .X. and .X.'
     .X.     ..X'
     X..     ..X'
rather than the y-symmetric bitmaps'
     ..X     X..'
     .X.     .X.'
     .X. and .X.'
     X..     ..X'
     X..     ..X'
A natural application would be to draw crosses using two DRAWLINEs as in'
    (PROGN (DRAWLINE -2 -4 2 4)'
           (DRAWLINE 2 -4 -2 4))'
But this gives us'
     X...X'
     .X..X'
     .X.X.'
     ..XX.'
     ..X..'
     ..XX.'
     .X.X.'
     .X..X'
     X...X'
instead of'
     X...X'
     .X.X.'
     .X.X.'
     ..X..'
     ..X..'
     .X.X.'
     .X.X.'
     X...X'
     X...X'
which is better.'
     If DRAWLINE implemented all of (1), (2), & (3), the following possibility can arise':  (DRAWLINE X2 Y2 X1 Y1 ...) may be slightly different than (DRAWLINE X1 Y1 X2 Y2 ...).  I consider this to be a desirable situation and this is also why I refer to the output of DRAWLINE as vectors.  The current implementation would appear to follow the principle':'
(4)  (DRAWLINE X2 Y2 X1 Y1 ...) and'
     (DRAWLINE X1 Y1 X2 Y2 ...) should be the same.'
This invariant is what we would expect in the Cartesian world.  However, not all Cartesian principles can be carried over into the bitmap world, and we must try to get the best principles, sacrificing the less valuable principles.  Adopting (4) forces a certain orientation in the bitmap world.  An ant staring down from the top of the screen would draw different conclusions about how DRAWLINE operates than an ant staring up from the bottom of the screen.  Similarly for left & right.  I think it ought to be the case that DRAWLINE obey the following more valuable principle':'
(5)  (DRAWLINE X2 Y2 X1 Y1 ...) can be rotated 180 degrees and then translated into (DRAWLINE X1 Y1 X2 Y2).'
All ants facing North, East, West, or South on the front side of the screen will now all agree about how DRAWLINE works.  You can call this the principle of xy relativity.'
Principle (5) is implied by principles (1)-(3).  Therefore, if (1)-(3) held, we could improve on our cross drawing even more by taking advantage of (5)':'
     (PROGN (DRAWLINE 2 4 0 0)'
            (DRAWLINE -2 4 0 0)'
            (DRAWLINE -2 -4 0 0)'
            (DRAWLINE 2 -4 0 0))'
giving us the bitmap'
     X...X'
     X...X'
     .X.X.'
     .X.X.'
     ..X..'
     .X.X.'
     .X.X.'
     X...X'
     X...X'
The existing algorithm again gives us'
     X...X'
     .X..X'
     .X.X.'
     ..XX.'
     ..X..'
     ..XX.'
     .X.X.'
     .X..X'
     X...X'
which is still as bad as ever.'
'
                       INADEQUACY #2'
'
     If the WIDTH argument to DRAWLINE is more than 1, we see DRAWLINE behave discontinuously near angles 45, 135, 225, 315.  DRAWLINE draws a parallelogram and two opposite sides will be parallel to the x-axis or y-axis according to which of 4 sectors Cartesian vector (X2-X1,Y2-Y1) points.  This anomalous behaviour means that if we want to depend on edges parallel to the x-axis, say, we must either use a loop and do repeated DRAWLINES with a WIDTH of 1, or do our own X2-X1,Y2-Y1 calculations to optimize two of our sectors and still use the loop for our other two other sectors.  Letting DRAWLINE decide for us whether to use a HORIZONTAL brush or a VERTICAL brsuh is just too clumsy.  It would be better for us to indicate directly to DRAWLINE what kind of brush to use when we need this control.  DRAWLINE with the following arguments is plausible':'
     (DRAWLINE X1 Y1 X2 Y2 BRUSH OPERATION STREAM COLOR)'
If BRUSH = (HORIZONTAL N), then this amounts to'
     (COND ((> Y2 Y1)'
            (FOR I FROM 0 TO (SUB1 WIDTH)'
             DO (DRAWLINE (IDIFFERENCE X1 I)'
                          Y1'
                          (IDIFFERENCE X2 I)'
                          Y2)))'
           (T (FOR I FROM 0 TO (SUB1 WIDTH)'
               DO (DRAWLINE (IPLUS X1 I)'
                            Y1'
                            (IPLUS X2 I)'
                            Y2)))'
If BRUSH = (VERTICAL N), then this amounts to'
     (COND ((> X2 X1)'
            (FOR I FROM 0 TO (SUB1 WIDTH)'
             DO (DRAWLINE X1'
                          (IPLUS Y1 I)'
                          X2'
                          (IPLUS Y2 I))))'
           (T (FOR I FROM 0 TO (SUB1 WIDTH)'
               DO (DRAWLINE X1'
                            (IDIFFERENCE Y1 I)'
                            X2'
                            (IDIFFERENCE Y2 I))))'
A BRUSH = (SQUARE N) can be implemented as two DRAWLINEs with HORIZONTAL & VERTICAL brushes and a BITBLT of a square.'
A BRUSH = (ROUND N) can be implemented as two thick DRAWCIRCLEs and a number of DRAWLINEs (probably we would use \CLIPANDDRAWLINE1''s here).  If BRUSH = N, a number, we would interpret this as (SQUARE N).'
     A (SQUARE N) vector pointed at 45 degrees appears 41% thicker than a (SQUARE N) vector pointed at 0 degrees.  The same phenomena occurs with the existing implementation.  This behaviour is correct and should not be changed.  It is better for the user to do the calculation'
     (SETQ DX (IABS (IDIFFERENCE X2 X1)))'
     (SETQ DY (IABS (IDIFFERENCE Y2 Y1)))'
     (COND ((NOT (OR (ZEROP DX) (ZEROP DY)))'
            (SETQ DIST (SQRT (IPLUS (ITIMES DX DX)'
                                    (ITIMES DY DY))))'
            (SETQ N (FIXR (FQUOTIENT (FTIMES DIST N)'
                                     (IPLUS DX DY))))))'
in his own code.  If the calculation were put in DRAWLINE''s code, then the user would have to undo this calculation if he did want the 41%, however FLOATP/FIXP conversions would prevent him from being able to undo the calculation exactly and therefore cause inprecision and loss of control over the shape of the output of DRAWLINE.  The maxim to follow is that smartish complicated calculations should be left to the user and DRAWLINE should be as simple and transparent as possible.'
'
                       INADEQUACY #3'
'
     This leads me to inadequacy number 3.  While DRAWLINE apparently gets the WIDTH of its output right, the output is offset by roughly WIDTH/2.  Apparently, Ron put this change into DRAWLINE last year.  I think this was a detrimental change.  This is the kind of "smart" calculation I describe in the previous paragraph that I wish system code would avoid.  To avoid Ron''s feature I actually wrote code to case out on which of 4 sectors I was in and add or subtract one of'
      (IQUOTIENT WIDTH 2)'
      (IQUOTIENT (SUB1 WIDTH) 2)'
to get the lines I really wanted.  I decided that the code was so unaesthetic and vulnerable to future unprincipled changes in DRAWLINE that I junked it and resorted to loops with WIDTH=1 args to my DRAWLINEs.  Basically, I am unable to use the WIDTH arg of DRAWLINE for precision work.'
     I think the WIDTH arg should be handled in the following way.  When the user asks for (DRAWLINE X1 Y1 X2 Y2 WIDTH ...) we imagine ourselves sitting on the Cartesian plane looking from tail (X1 . Y1) to head (X2 . Y2) of the X1 Y1 X2 Y2 vector.  We draw the vector we are sitting on and WIDTH-1 vectors like it to our left (see the code I offer for my HORIZONTAL and VERTICAL brsuhes above).  The vector we are sitting on will always be pointing counterclockwise on the perimeter of the parallelogram we have drawn, agreeing with standard mathematical convention.'
'
                         SUMMARY'
'
     My experience in trying to use DRAWLINE for detailed work leads me to believe that its existing algorithm and interface are lacking.  DRAWLINE''s output fails to have all the nice xy symmetry properties I describe under my first section.  DRAWLINE decides for me whether to use a HORIZONTAL brush or a VERTICAL brush causing discontiuities at 45, 135, 225, and 315 degrees.  DRAWLINE''s feature offsetting coordinates by WIDTH/2 is unhelpful to me.  These "smart" decisions by DRAWLINE only appear smart if you actually want them, and otherwise appear to be very dumb and hard to work around.  The DRAWLINE algorithm is too opaque and I am unable to use DRAWLINE''s WIDTH and still get the fine control I want.  I must resort to multiple DRAWLINEs instead.  In my opinion, it is better for "smart" calculations to be done by the caller of DRAWLINE.  Implementation of my suggestions in the previous 3 sections would make for a better, simpler, more transparent algorithm.

Workaround: 

Test Case: 

Edit-By: 

Edit-Date: 13-Aug-84 12':03':20

Attn: Burton, Kaplan

Assigned To: 

In/By: 

Disposition: 

System: Windows and Graphics

Subsystem: Other

Machine: 1132

Disk: 

Microcode Version: 5124

Memory Size: 4096

File Server: 

Server Software Version: 

Difficulty: 

Frequency: Everytime

Impact: Moderate

Priority: Perhaps

Status: Open

Problem Type: Design - UI

Source Files: