Drawing the Rows

*AutoLISP Reference*. For now, just read the code; do not
write anything.

(defun gp:Calculate-and-Draw-Tiles (BoundaryData / PathLength

TileSpace TileRadius SpaceFilled SpaceToFill

RowSpacing offsetFromCenter

rowStartPoint pathWidth pathAngle

ObjectCreationStyle TileList)

(setq PathLength (cdr (assoc 41 BoundaryData))

TileSpace (cdr (assoc 43 BoundaryData))

TileRadius (cdr (assoc 42 BoundaryData))

SpaceToFill (- PathLength TileRadius)

RowSpacing (* (+ TileSpace (* TileRadius 2.0))

(sin (Degrees->Radians 60))

) ;_ end of *

SpaceFilled RowSpacing

offsetFromCenter 0.0

offsetDistance (/ (+ (* TileRadius 2.0) TileSpace) 2.0)

rowStartPoint (cdr (assoc 10 BoundaryData))

pathWidth (cdr (assoc 40 BoundaryData))

pathAngle (cdr (assoc 50 BoundaryData))

ObjectCreationStyle (strcase (cdr (assoc 3 BoundaryData)))

) ;_ end of setq

;; Compensate for the first call to gp:calculate-Draw-tile Row

;; in the loop below.

(setq rowStartPoint

(polar rowStartPoint

(+ pathAngle pi)

(/ TileRadius 2.0)

) ;_ end of polar

) ;_ end of setq

;; Draw each row of tiles.

(while (<= SpaceFilled SpaceToFill)

;; Get the list of tiles created, adding them to our list.

(setq tileList (append tileList

(gp:calculate-Draw-TileRow

(setq rowStartPoint

(polar rowStartPoint

pathAngle

RowSpacing

) ;_ end of polar

) ;_ end of setq

TileRadius

TileSpace

pathWidth

pathAngle

offsetFromCenter

ObjectCreationStyle

) ;_ end of gp:calculate-Draw-TileRow

) ;_ end of append

;; Calculate the distance along the path for the next row.

SpaceFilled (+ SpaceFilled RowSpacing)

;; Alternate between a zero and a positive offset

;; (causes alternate rows to be indented).

offsetFromCenter

(if (= offsetFromCenter 0.0)

offsetDistance

0.0

) ;_ end of if

) ;_ end of setq

) ;_ end of while

;; Return the list of tiles created.

tileList

) ;_ end of defun

A couple of sections from the code may need a little extra explanation.

*while* loop begins:

;; Compensate for the very first start point!!

(setq rowStartPoint(polar rowStartPoint

(+ pathAngle pi)(/ TileRadius 2.0)))

There are three pieces to the puzzle of figuring out the logic behind this algorithm:

- The rowStartPoint variable starts its
life within the
*gp:Calculate-and-Draw-Tiles*function by being assigned the point the user selected as the start point of the path. - The very first argument passed to the
*gp:calculate-Draw-TileRow*function does the following:(setq rowStartPoint(polar rowStartPoint pathAngle RowSpacing))

Another way of stating this is: At the time the*gp:calculate-Draw-TileRow*function is called, the rowStartPoint variable is set to one RowSpacing distance beyond the current rowStartPoint. - The rowStartPoint argument is used
within
*gp:calculate-Draw-TileRow*as the starting point for the centers of the circles in the row.

rowStartPoint during the drawing of the first row
(that is, the first cycle through the *while* loop), you will want to
shift rowStartPoint slightly in the
opposite direction. The aim is to avoid the appearance of a large
margin of empty space between the path boundary and the first row.
Half the TileRadius is a sufficient
amount by which to move the point. This can be achieved by using
*polar*
to project rowStartPoint along a vector
oriented 180 degrees from the PathAngle.
If you think about it, this places the point temporarily outside
the path boundary.

The next fragment (modified for readability) may be a little puzzling:

(setq tileList (append tileList

(gp:calculate-Draw-TileRow

(setq rowStartPoint

(polar rowStartPoint pathAngle RowSpacing)

) ;_ end of setq

TileRadius TileSpace pathWidth pathAngle

offsetFromCenter ObjectCreationStyle

)))

*setq* wrapped around an
*append* wrapped around the call to
*gp:calculate-Draw-TileRow*.

*gp:calculate-Draw-TileRow* function
will return the Object IDs for each tile drawn. (The Object ID
points to the tile object in the drawing.) You are drawing the
tiles row by row, so the function returns the Object IDs of one row
at a time. The *append* function adds the new
Object IDs to any existing Object IDs stored in tileList.

Near the end of the function, you can find the following code fragment:

(setq offsetFromCenter

(if (= offsetFromCenter 0.0)

offsetDistance

0.0

)

)

This is the offset toggle, which determines whether the row being drawn should begin with a circle centered on the path or offset from the path. The pseudo-code for this algorithm follows:

Set the offset amount to the following:

If the offset is currently zero, set it to the offset distance;

Otherwise, set it back to zero.