# Recursive tower has extra walls

458
6
Jump to solution
01-20-2014 11:26 AM
New Contributor
I've got a CGA rule that creates a building that has a pedestal and 2 towers on top of the pedestal. The towers are set back from the edge of the pedestal and then extruded, they look okay as well except that duplicate walls are created that extend from the edge of the pedestal, as in the image below:

[ATTACH=CONFIG]30640[/ATTACH]

the code I used is below, can anyone tell me what I did to cause this phenomenon?

`Pedestal -->  extrude(world.y, ((Num_Pedestal_Floors * Upperfloor_Height) + (Groundfloor_Height - Upperfloor_Height)))  PedBuildingVolume3D  PedBuildingVolume3D -->  case (Groundfloor_Height != (Num_Pedestal_Floors * Upperfloor_Height) + (Groundfloor_Height - Upperfloor_Height)) : #pedestal height is NOT equal to height of just the ground floor   # the 3d volume will be split into smaller 3d volumes ! 1 ground floor volume will be created.   split(y) {Groundfloor_Height : Volume("GF") | ~1 : PedAllUpperFloors}  else:   Volume("GF1")   Towers   PedAllUpperFloors -->  # the rest of the volume is not split into upper floor volumes, as many times as possible ('*' sign)  split(y) {~Upperfloor_Height : Volume("UF")}*  Towers   Volume(volumeType) -->  case volumeType == "GF1" :   case ((split.index == 0) && (NumFlrsComm >= 1)):     comp(f){side: Simple_Com | bottom: FloorBottom | top : Top | all: NIL }     set(material.opacity,OpacityVal)     CommReporting     MassReporting   case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix >= 1)):     comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top | all: NIL }     set(material.opacity,OpacityVal)     MixReporting     MassReporting   case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix == 0) && (NumFlrOff >= 1)):     comp(f){side: Simple_Off | bottom: FloorBottom | top : Top | all: NIL }     set(material.opacity,OpacityVal)     OffReporting     MassReporting   case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix == 0) && (NumFlrOff == 0)):     comp(f){side: Simple_Res | bottom: FloorBottom | top : Top | all: NIL }     set(material.opacity,OpacityVal)     ResReporting     MassReporting       else:    NIL  case volumeType == "GF" :   case ((split.index == 0) && (NumFlrsComm >= 1)):     comp(f){side: Simple_Com | bottom: FloorBottom | top : Top | all: NIL }     set(material.opacity,OpacityVal)     CommReporting     MassReporting   case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix >= 1)):     comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top | all: NIL }     set(material.opacity,OpacityVal)     MixReporting     MassReporting   case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix == 0) && (NumFlrOff >= 1)):     comp(f){side: Simple_Off | bottom: FloorBottom | top : Top | all: NIL }     set(material.opacity,OpacityVal)     OffReporting     MassReporting   case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix == 0) && (NumFlrOff == 0)):     comp(f){side: Simple_Res | bottom: FloorBottom | top : Top | all: NIL }     set(material.opacity,OpacityVal)     ResReporting     MassReporting   else:    NIL  case volumeType == "UF" :   case (((split.index + 1) <= (NumFlrsComm - 1)) && (NumFlrsComm > 1)):     comp(f){side: Simple_Com | bottom: FloorBottom | top : Top }     CommReporting     MassReporting   case (((split.index + 1) > (NumFlrsComm - 1)) && (NumFlrMix > 0) && ((split.index + 1) <= ((NumFlrsComm + NumFlrMix) - 1))):     comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top }     MixReporting     MassReporting   case (((split.index + 1) > ((NumFlrsComm - 1) + (NumFlrMix - 1))) && (NumFlrOff > 0) && ((split.index + 1) <= ((NumFlrsComm + NumFlrMix + NumFlrOff) - 1))):     comp(f){side: Simple_Off | bottom: FloorBottom | top : Top }     OffReporting     MassReporting   case ((split.index + 1) > (NumFlrsComm + NumFlrMix + NumFlrOff) - 1):     comp(f){side: Simple_Res | bottom: FloorBottom | top : Top }     ResReporting     MassReporting   else:    NIL  else:   NIL  Towers -->  case xLength > zLength :    split(x) {theLength/2 : Tower1 | ~1 : Tower2 }  else :   split(z) {(theLength/2) : Tower1 | ~1 : Tower2 }    Tower1 -->   setback(FSetbackT1) { street.front : Concrete | remainder : T1Sub1 }  T1Sub1 --> setback(BSetbackT1) { street.back : Concrete | remainder : T1Sub2 }  T1Sub2 --> setback(LSetbackT1) { street.left : Concrete | remainder : T1Sub3 }  T1Sub3 --> setback(RSetbackT1) { street.right : Concrete | remainder : Tower1Extrude }  Tower1Extrude -->  extrude(world.y, (Tower1_Floors * Upperfloor_Height))  T1BuildingVolume3D  T1BuildingVolume3D -->  # the volume is split into upper floor volumes, as many times as possible ('*' sign)  split(y) {~Upperfloor_Height : T1Volume}*  T1Volume -->    case (split.index <= (NumFlrComm1 - 1)):    comp(f){side: Simple_Com | bottom: FloorBottom | top : Top }    CommReporting    MassReporting  case ((split.index > (NumFlrComm1 - 1)) && (NumFlrMix1 > 0) && ((split.index) <= ((NumFlrComm1 + NumFlrMix1) - 1))):    comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top }    MixReporting    MassReporting  case (((split.index) > ((NumFlrComm1 + NumFlrMix1) - 1)) && (NumFlrOff1 > 0) && ((split.index) <= ((NumFlrComm1 + NumFlrMix1 + NumFlrOff1) - 1))):    comp(f){side: Simple_Off | bottom: FloorBottom | top : Top }    OffReporting    MassReporting  case ((split.index) > (NumFlrComm1 + NumFlrMix1 + NumFlrOff1) - 1):   else:    comp(f){side: Simple_Res | bottom: FloorBottom | top : Top }    ResReporting    MassReporting  else:   NIL  Tower2 -->  setback(FSetbackT2) { street.front : Concrete | remainder : T2Sub1 }  T2Sub1 --> setback(BSetbackT2) { street.back : Concrete | remainder : T2Sub2 }  T2Sub2 --> setback(LSetbackT2) { street.left : Concrete | remainder : T2Sub3 }  T2Sub3 --> setback(RSetbackT2) { street.right : Concrete | remainder : Tower2Extrude }  Tower2Extrude -->  extrude(world.y, (Tower2_Floors * Upperfloor_Height))  T2BuildingVolume3D  T2BuildingVolume3D -->  # the rest of the volume is not split into upper floor volumes, as many times as possible ('*' sign)  split(y) {~Upperfloor_Height : T2Volume}*  T2Volume -->   case (split.index <= (NumFlrComm2 - 1)):    comp(f){side: Simple_Com | bottom: FloorBottom | top : Top }    CommReporting    MassReporting  case ((split.index > (NumFlrComm2 - 1)) && (NumFlrMix2 > 0) && ((split.index) <= ((NumFlrComm2 + NumFlrMix2) - 1))):    comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top }    MixReporting    MassReporting  case (((split.index) > ((NumFlrComm2 + NumFlrMix2) - 1)) && (NumFlrOff2 > 0) && ((split.index) <= ((NumFlrComm2 + NumFlrMix2 + NumFlrOff2) - 1))):    comp(f){side: Simple_Off | bottom: FloorBottom | top : Top }    OffReporting    MassReporting  case ((split.index) > (NumFlrComm2 + NumFlrMix2 + NumFlrOff2) - 1):    comp(f){side: Simple_Res | bottom: FloorBottom | top : Top }    ResReporting    MassReporting  else:   NIL   Simple_Com --> color(ComColor)  set(material.opacity,OpacityVal)  Simple_Mix --> color(MixColor)  set(material.opacity,OpacityVal)  Simple_Off --> color(OffColor)  set(material.opacity,OpacityVal)  Simple_Res --> color(ResColor)  set(material.opacity,OpacityVal)`
Tags (3)
1 Solution

Accepted Solutions
Frequent Contributor II
Ok..

well, if you need a lot of such precise control, the code may get a bit complicated.

But in general, I'd try to never copy rule calls, e.g. like for reporting.

e.g. instead of calling the report rule from within every case statement, just call it once in the next rule.

What may help is to create so-called generic attributes. That way, you can pass everything down without rule parameters and can work with less case statements.

Pumping all geometries and all volumes through the same logic streamlines the code a lot..

A lot of theory.. sorry. :)

I'd like to help you out with coding this more properly, but I'm swamped with work right now .. :(

a bit cooler/more automatted reporting :
Note that this automatically accumulates the totals in Vol & GFA too.
`Reporting -->     report("Vol." + myUsageAttribute, geometry.volume)     report("GFA." + myUsageAttribute, geometry.area(bottom))`
6 Replies
New Contributor
I had to simplify the code to make it fit and I missed an else statement that should have been deleted. The new code is below:

`Pedestal --> extrude(world.y, ((Num_Pedestal_Floors * Upperfloor_Height) + (Groundfloor_Height - Upperfloor_Height))) PedBuildingVolume3DPedBuildingVolume3D --> case (Groundfloor_Height != (Num_Pedestal_Floors * Upperfloor_Height) + (Groundfloor_Height - Upperfloor_Height)) : #pedestal height is NOT equal to height of just the ground floor  # the 3d volume will be split into smaller 3d volumes ! 1 ground floor volume will be created.  split(y) {Groundfloor_Height : Volume("GF") | ~1 : PedAllUpperFloors} else:  Volume("GF1")  Towers PedAllUpperFloors --> # the rest of the volume is not split into upper floor volumes, as many times as possible ('*' sign) split(y) {~Upperfloor_Height : Volume("UF")}* TowersVolume(volumeType) --> case volumeType == "GF1" :  case ((split.index == 0) && (NumFlrsComm >= 1)):    comp(f){side: Simple_Com | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    CommReporting    MassReporting  case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix >= 1)):    comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    MixReporting    MassReporting  case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix == 0) && (NumFlrOff >= 1)):    comp(f){side: Simple_Off | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    OffReporting    MassReporting  case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix == 0) && (NumFlrOff == 0)):    comp(f){side: Simple_Res | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    ResReporting    MassReporting     else:   NIL case volumeType == "GF" :  case ((split.index == 0) && (NumFlrsComm >= 1)):    comp(f){side: Simple_Com | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    CommReporting    MassReporting  case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix >= 1)):    comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    MixReporting    MassReporting  case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix == 0) && (NumFlrOff >= 1)):    comp(f){side: Simple_Off | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    OffReporting    MassReporting  case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix == 0) && (NumFlrOff == 0)):    comp(f){side: Simple_Res | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    ResReporting    MassReporting  else:   NIL case volumeType == "UF" :  case (((split.index + 1) <= (NumFlrsComm - 1)) && (NumFlrsComm > 1)):    comp(f){side: Simple_Com | bottom: FloorBottom | top : Top }    CommReporting    MassReporting  case (((split.index + 1) > (NumFlrsComm - 1)) && (NumFlrMix > 0) && ((split.index + 1) <= ((NumFlrsComm + NumFlrMix) - 1))):    comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top }    MixReporting    MassReporting  case (((split.index + 1) > ((NumFlrsComm - 1) + (NumFlrMix - 1))) && (NumFlrOff > 0) && ((split.index + 1) <= ((NumFlrsComm + NumFlrMix + NumFlrOff) - 1))):    comp(f){side: Simple_Off | bottom: FloorBottom | top : Top }    OffReporting    MassReporting  case ((split.index + 1) > (NumFlrsComm + NumFlrMix + NumFlrOff) - 1):    comp(f){side: Simple_Res | bottom: FloorBottom | top : Top }    ResReporting    MassReporting  else:   NIL else:  NILTowers --> case xLength > zLength :   split(x) {theLength/2 : Tower1 | ~1 : Tower2 } else :  split(z) {(theLength/2) : Tower1 | ~1 : Tower2 } Tower1 --> setback(FSetbackT1) { street.front : Concrete | remainder : T1Sub1 }T1Sub1 --> setback(BSetbackT1) { street.back : Concrete | remainder : T1Sub2 }T1Sub2 --> setback(LSetbackT1) { street.left : Concrete | remainder : T1Sub3 }T1Sub3 --> setback(RSetbackT1) { street.right : Concrete | remainder : Tower1Extrude }Tower1Extrude --> extrude(world.y, (Tower1_Floors * Upperfloor_Height)) T1BuildingVolume3DT1BuildingVolume3D --> # the volume is split into upper floor volumes, as many times as possible ('*' sign) split(y) {~Upperfloor_Height : T1Volume}*T1Volume -->  case (split.index <= (NumFlrComm1 - 1)):   comp(f){side: Simple_Com | bottom: FloorBottom | top : Top }   CommReporting   MassReporting case ((split.index > (NumFlrComm1 - 1)) && (NumFlrMix1 > 0) && ((split.index) <= ((NumFlrComm1 + NumFlrMix1) - 1))):   comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top }   MixReporting   MassReporting case (((split.index) > ((NumFlrComm1 + NumFlrMix1) - 1)) && (NumFlrOff1 > 0) && ((split.index) <= ((NumFlrComm1 + NumFlrMix1 + NumFlrOff1) - 1))):   comp(f){side: Simple_Off | bottom: FloorBottom | top : Top }   OffReporting   MassReporting case ((split.index) > (NumFlrComm1 + NumFlrMix1 + NumFlrOff1) - 1):   comp(f){side: Simple_Res | bottom: FloorBottom | top : Top }   ResReporting   MassReporting else:  NILTower2 --> setback(FSetbackT2) { street.front : Concrete | remainder : T2Sub1 }T2Sub1 --> setback(BSetbackT2) { street.back : Concrete | remainder : T2Sub2 }T2Sub2 --> setback(LSetbackT2) { street.left : Concrete | remainder : T2Sub3 }T2Sub3 --> setback(RSetbackT2) { street.right : Concrete | remainder : Tower2Extrude }Tower2Extrude --> extrude(world.y, (Tower2_Floors * Upperfloor_Height)) T2BuildingVolume3DT2BuildingVolume3D --> # the rest of the volume is not split into upper floor volumes, as many times as possible ('*' sign) split(y) {~Upperfloor_Height : T2Volume}*T2Volume -->  case (split.index <= (NumFlrComm2 - 1)):   comp(f){side: Simple_Com | bottom: FloorBottom | top : Top }   CommReporting   MassReporting case ((split.index > (NumFlrComm2 - 1)) && (NumFlrMix2 > 0) && ((split.index) <= ((NumFlrComm2 + NumFlrMix2) - 1))):   comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top }   MixReporting   MassReporting case (((split.index) > ((NumFlrComm2 + NumFlrMix2) - 1)) && (NumFlrOff2 > 0) && ((split.index) <= ((NumFlrComm2 + NumFlrMix2 + NumFlrOff2) - 1))):   comp(f){side: Simple_Off | bottom: FloorBottom | top : Top }   OffReporting   MassReporting case ((split.index) > (NumFlrComm2 + NumFlrMix2 + NumFlrOff2) - 1):   comp(f){side: Simple_Res | bottom: FloorBottom | top : Top }   ResReporting   MassReporting else:  NILSimple_Com --> color(ComColor) set(material.opacity,OpacityVal)Simple_Mix --> color(MixColor) set(material.opacity,OpacityVal)Simple_Off --> color(OffColor) set(material.opacity,OpacityVal)Simple_Res --> color(ResColor) set(material.opacity,OpacityVal)`
New Contributor
So I've solved the extra wall issue but now I've got duplicate towers, one set that is extruding from the top floor  of the pedestal but also a set that extrudes from the top of the first floor of the pedestal. I thought that the split only effected the current polygon?

The model now looks like the following:

[ATTACH=CONFIG]30663[/ATTACH]

the code now looks like this:

`Pedestal --> extrude(world.y, ((Num_Pedestal_Floors * Upperfloor_Height) + (Groundfloor_Height - Upperfloor_Height))) PedBuildingVolume3DPedBuildingVolume3D --> case (Groundfloor_Height != ((Num_Pedestal_Floors * Upperfloor_Height) + (Groundfloor_Height - Upperfloor_Height))) : #pedestal height is NOT equal to height of just the ground floor  # the 3d volume will be split into smaller 3d volumes ! 1 ground floor volume will be created.  split(y) {Groundfloor_Height : Volume("GF") | ~1 : PedAllUpperFloors} else:  split(y) {Groundfloor_Height : Volume("GF")}  report("NUMFLRS",NumFlrs)  Towers PedAllUpperFloors --> # the rest of the volume is not split into upper floor volumes, as many times as possible ('*' sign) split(y) {~Upperfloor_Height : Volume("UF")}* NIL TowersVolume(volumeType) --> case volumeType == "GF" :  case ((split.index == 0) && (NumFlrsComm >= 1)):    comp(f){side: Simple_Com | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    report("SPLITTOT", split.total)    CommReporting    MassReporting  case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix >= 1)):    comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    report("SPLITTOT", split.total)    MixReporting    MassReporting  case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix == 0) && (NumFlrOff >= 1)):    comp(f){side: Simple_Off | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    report("SPLITTOT", split.total)    OffReporting    MassReporting  case ((split.index == 0) && (NumFlrsComm == 0) && (NumFlrMix == 0) && (NumFlrOff == 0)):    comp(f){side: Simple_Res | bottom: FloorBottom | top : Top | all: NIL }    set(material.opacity,OpacityVal)    report("SPLITTOT", split.total)    ResReporting    MassReporting  else:   NIL case volumeType == "UF" :  case ((split.total <= Num_Pedestal_Floors) && (((split.index + 1) <= (NumFlrsComm - 1)) && (NumFlrsComm > 1))):    comp(f){side: Simple_Com | bottom: FloorBottom | top : Top }    report("SPLITTOT", split.total)    CommReporting    MassReporting  case ((split.total <= Num_Pedestal_Floors) && ((split.index + 1) > (NumFlrsComm - 1)) && (NumFlrMix > 0) && ((split.index + 1) <= ((NumFlrsComm + NumFlrMix) - 1))):    comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top }    report("SPLITTOT", split.total)    MixReporting    MassReporting  case ((split.total <= Num_Pedestal_Floors) && ((split.index + 1) > ((NumFlrsComm - 1) + (NumFlrMix - 1))) && (NumFlrOff > 0) && ((split.index + 1) <= ((NumFlrsComm + NumFlrMix + NumFlrOff) - 1))):    comp(f){side: Simple_Off | bottom: FloorBottom | top : Top }    report("SPLITTOT", split.total)    OffReporting    MassReporting  case ((split.total <= Num_Pedestal_Floors) && (split.index + 1) > (NumFlrsComm + NumFlrMix + NumFlrOff) - 1):    comp(f){side: Simple_Res | bottom: FloorBottom | top : Top }    report("SPLITTOT", split.total)    ResReporting    MassReporting  else:   NIL else:  NILTowers --> case xLength > zLength :   split(x) {'.5 : Tower1 | '.5 : Tower2 }  # I expected this split to split the polygon at the top of the pedestal, but it appears to else :           # also split the top of the first floor of the pedestal and extrudes from both location, why?  split(z) {'.5 : Tower1 | '.5 : Tower2 } Tower1 --> setback(FSetbackT1) { street.front : Concrete | remainder : T1Sub1 }T1Sub1 --> setback(BSetbackT1) { street.back : Concrete | remainder : T1Sub2 }T1Sub2 --> setback(LSetbackT1) { street.left : Concrete | remainder : T1Sub3 }T1Sub3 --> setback(RSetbackT1) { street.right : Concrete | remainder : Tower1Extrude }Tower1Extrude --> extrude(world.y, (Tower1_Floors * Upperfloor_Height)) T1BuildingVolume3D  T1BuildingVolume3D --> # the volume is split into upper floor volumes, as many times as possible ('*' sign) split(y) {~Upperfloor_Height : T1Volume}*T1Volume -->  case ((split.total <= Tower1_Floors) && (split.index <= (NumFlrComm1 - 1))):   comp(f){side: Simple_Com | bottom: FloorBottom | top : Top }   CommReporting   MassReporting case ((split.total <= Tower1_Floors) && ((split.index > (NumFlrComm1 - 1)) && (NumFlrMix1 > 0) && ((split.index) <= ((NumFlrComm1 + NumFlrMix1) - 1)))):   comp(f){side: Simple_Mix | bottom: FloorBottom | top : Top }   MixReporting   MassReporting case ((split.total <= Tower1_Floors) && (((split.index) > ((NumFlrComm1 + NumFlrMix1) - 1)) && (NumFlrOff1 > 0) && ((split.index) <= ((NumFlrComm1 + NumFlrMix1 + NumFlrOff1) - 1)))):   comp(f){side: Simple_Off | bottom: FloorBottom | top : Top }   OffReporting   MassReporting case ((split.total <= Tower1_Floors) && ((split.index) > (NumFlrComm1 + NumFlrMix1 + NumFlrOff1) - 1)):   comp(f){side: Simple_Res | bottom: FloorBottom | top : Top }   ResReporting   MassReporting else:  NIL`
Frequent Contributor II
Hi !

You still have an awful amout of code duplicated. I'm sure you can still erase lots of that. Especially in relation to those reports.

I know it's difficult to track this down ..

This here may help you if you've not seen it already :

Also, make absolutely sure you use the Model Hierarchy to track these things down.

Check here :

http://forums.arcgis.com/threads/44417-CGA-Understanding-the-concept-of-the-scope

Let me know how you progress !

Matt
New Contributor
Thanks for the feedback Matt.
I did manage to solve the problem, I was missing a component operation when I branched from the pedestal to the towers.

As for the duplicate code, I'm not sure how I can clean it up, I'm dealing with a report that requires that I report on the 4 floor use types as well as having the ability to independently modify the floor use makeup of the pedestal and each of the 2 towers.
Frequent Contributor II
Ok..

well, if you need a lot of such precise control, the code may get a bit complicated.

But in general, I'd try to never copy rule calls, e.g. like for reporting.

e.g. instead of calling the report rule from within every case statement, just call it once in the next rule.

What may help is to create so-called generic attributes. That way, you can pass everything down without rule parameters and can work with less case statements.

Pumping all geometries and all volumes through the same logic streamlines the code a lot..

A lot of theory.. sorry. :)

I'd like to help you out with coding this more properly, but I'm swamped with work right now .. :(

a bit cooler/more automatted reporting :
Note that this automatically accumulates the totals in Vol & GFA too.
`Reporting -->     report("Vol." + myUsageAttribute, geometry.volume)     report("GFA." + myUsageAttribute, geometry.area(bottom))`
New Contributor
Thanks for the tip Matt. Using attributes for the report items does indeed clean up 3/4 of the code I had be using for reporting. This is something I'll use from now on and, if I get a chance, I'll go back to previous rule files and clean them up as well.
Thanks again, good tip!