Wall example - sequences, positioning and collating outputs

<-Previous | ^UP^ | Next->

Up to now we have covered the basics of

  • Defining & Instantiating GendL objects
  • Positioning and orienting geometry
  • Defining child objects and sequences of child objects
  • Dealing with numbers and lists
  • Defining standard CL functions and GendL object functions
This tutorial aims to bring the above concepts together with a tangible example. Starting with the example briefing below, you can either try to develop your own solution or build up a solution in a guided step-by-step manner by clicking the Hint button

Example Briefing

Imagine a wall is built from bricks which are 180mm long, 45mm high and 90mm wide. Each course (i.e. row) of bricks sits on a bed of mortar which is 10mm thick, and each brick is joined to its lateral neighbor(s) with mortar having a nominal joint thickness of 10mm. While a wall instance can be specified using nominal dimensions for length and height, the actual dimensions may vary slightly in order to use a whole number of bricks per row. Vertically adjacent rows of bricks are offset by half a brick with respect to the row below and so will consist of a half-brick at the beginning and a half-brick at the end of the row (i.e. row).

Define and instantiate a GendL model of a wall which has a default nominal height of 900mm and a nominal length of 3700mm, and report the number of full bricks and number of half bricks used. Assuming the density of mortar is 2182kg/m3 determine also the mass of mortar used

Start by thinking of the structure

  • A wall has rows of bricks and mortar.
  • A row of bricks and morter has a row of bricks seperated by mortar joints, sat on a bed of mortar
  • A row of bricks seperated by mortar joints is made of full bricks and half bricks and mortar
  • A bed of mortar sits below every row of bricks separated by mortar joints
And from that conceptual description, lay down a definition for an outline object structure. Note that while as yet it contains neither dimensions nor mixins, at its leaf level it is already using GendL wireframe geometry primitives

(define-object wall():objects((row :type 'row)))(define-object row ():objects((bricks-and-mortar :type 'bricks-and-mortar)(mortar-bed :type 'box)))(define-object bricks-and-mortar ():objects((full-brick :type 'box)(half-brick :type 'box)(mortar-joint :type 'box)))

Working from the bottom with the GendL leaf instances of brick, half-brick and mortar-joint (all standard boxes), determine appropriate referencing expressions for their dimensional inputs. This will also inform as to what :input-slots you will need coming into the bricks-and-mortar parent object.

(define-object bricks-and-mortar ():input-slots(brick-heightbrick-lengthbrick-widthmortar-joint-width):objects((full-brick :type 'box:length (the brick-length):height (the brick-height):width (the brick-width))(half-brick :type 'box:length (half (the brick-length)):height (the brick-height):width (the brick-width))(mortar-joint :type 'box:height (the brick-height):width (the brick-width):length (the mortar-joint-width))))

Then move up to the row object and repeat

(define-object row ():input-slots(brick-heightbrick-lengthbrick-widthmortar-joint-width):objects((bricks-and-mortar :type 'bricks-and-mortar:brick-height (the brick-height):brick-length (the brick-length):brick-width (the brick-width):mortar-joint-width (the mortar-joint-width))(mortar-bed :type 'box:height (the mortar-joint-width))))

Then move up to the wall object and repeat, but with this object add the default values for :input-slots, and the other 2 known inputs wall-height and wall-length

(define-object wall():input-slots((brick-height 45)(brick-length 180)(brick-width 90)(mortar-joint-width 10)(wall-length 3700)(wall-height 900)):objects((row :type 'row:brick-height(the brick-height):brick-length (the brick-length):brick-width (the brick-width):mortar-joint-width (the mortar-joint-width))))

Now working from the top down you need to determine the actual overall dimensions of the wall and from the the number of rows. If you use a box mixin for the wall object and specify its width, length, and height appropriately (and leaving center and orientation to their default values for now), then you can probe and display its reference box i.e. bounding-box. Having calculated the number-of-rows, you can also set the :sequence (:size ) for the row object and additionally pass in the bricks-per-row, width and length. Compiling wall and displaying in Geysr, you can show the overall bounding box and see the sequence of row objects

(define-object wall(box):input-slots((brick-height 45)(brick-length 180)(brick-width 90)(mortar-joint-width 10)(wall-length 3700)(wall-height 900)):computed-slots((row-height (+ (the brick-height) (the mortar-joint-width)))(number-of-rows (round-to-nearest (div (the wall-height) (the row-height)) 1))(actual-wall-height (* (the row-height) (the number-of-rows)));; for the wall-length we need the number of full bricks;; if there are n full bricks then there will be (n-1) mortar joints;; so n*brick-length + n-1*mortar-joint-width = overall-length;; or n(brick-length + mortar-join-width) - mortar-joint-width = overall-length;; or n = (overall-length - mortar-joint-width)/(brick-length + mortar-joint-width)(number-of-bricks (round-to-nearest (div (- (the wall-length) (the mortar-joint-width))(+ (the brick-length) (the mortar-joint-width)))1))(actual-wall-length (+ (* (the number-of-bricks) (the brick-length))(* (- (the number-of-bricks) 1) (the mortar-joint-width))));; box inputs - gives the wall bounding box(height (the actual-wall-height))(width (the brick-width))(length (the actual-wall-length))):objects((row :type 'row:sequence (:size (the number-of-rows)):bricks-per-row (the number-of-bricks):length (the length):width (the width):brick-height(the brick-height):brick-length (the brick-length):brick-width (the brick-width):mortar-joint (the mortar-joint-width))))

The next task is to position each row of bricks, first by positioning the bounding box for each row. Each row is (the brick-height) + (the mortar-jpint-width) high. The center of the first row is half of this dimension above the bottom of the wall, and the center of each subsequent row is the row height above the center of the previous row. Updating the definition of row to use box as its mixin and then specifying :center and :height is sufficient to define and position each row of the wall. The code below shows just the update to the definition of the row child object of wall

(define-object wall(box).........:objects((row :type 'row:sequence (:size (the number-of-rows)):center (translate-along-vector (the (face-center :bottom))(the (face-normal-vector :top))(+ (half (the-child height))(* (the-child index) (the-child height)))):length (the length):width (the width):height (+ (the brick-height) (the mortar-joint-width))):bricks-per-row (the number-of-bricks):brick-height(the brick-height):brick-length (the brick-length):brick-width (the brick-width):mortar-joint-width (the mortar-joint-width))