In this tutorial we will annotate a model by adding section levels and we will produce and emit building metrics to Excel. This is part of the joint exercise of performing a massing study for a building and producing a mold for casting. Interim steps have been presented previously in separate posts.

## Technique

- Apply the same logic of slicing solid models to produce contours but this time use the information for creating spread sheets and annotating a building section a-la Building Information Modeling.
- Use the AreaMassProperties object to compute all sorts of interesting geometric properties such as mass, area, moments of inertia, centroid etc.
- Format and compound text to form a spread sheet table which may be emitted into a panel or copied directly into the clipboard such that it can be pasted into Excel.

## Procedure

```
private void RunScript(Brep Mass, Brep Core, double FloorHeight,
ref object Geometry, ref object AnnoPnts,
ref object AnnoTxts, ref object Excel)
{
//-- Lesson: Break Complex Processes into
//-- logical tasks. Each time store info into
//-- lists. Keep minimal loop nesting.
//--
var geometry = new List<object>();
//-- To Calculate the number of Slices Needed
//--
BoundingBox bounds = Mass.GetBoundingBox(true);
var zmin = bounds.Min.Z;
var zmax = bounds.Max.Z;
var count = (int) ((zmax - zmin) / FloorHeight);
if( count == 0)
{
Print("Nothing to Cut, Bye!");
return;
}
//-- To Produce the Planes for Areas
//--
var planes = new List<Plane>();
for( var index = 0; index < count; index++ )
{
int level = index;
double height = level * FloorHeight + 1.5; //<-- +1.5m above FFL
Point3d origin = new Point3d(0, 0, height);
Plane plane = new Plane(origin, Vector3d.ZAxis);
planes.Add(plane);
///geometry.Add(plane);
}
//-- To Produce the Mass Outlines
//--
var mass_curves = new List<Curve>();
for( var index = 0; index < count; index++ )
{
Curve[] curves;
Point3d[] points;
Rhino.Geometry.Intersect.Intersection.BrepPlane(
Mass, planes[index], 0.0001, out curves, out points);
//-- Complete Failure
//--
if( curves.Length == 0)
{
Print("Failed at Level " + index.ToString());
return;
}
//-- Numerical Issue or Topology Issue
//--
if( curves.Length != 1)
{
Print("Something is fishy at Level " + index.ToString());
}
mass_curves.Add(curves[0]);
geometry.Add(curves[0]);
}
//-- To Produce the Core Outlines (Same as above)
//-- Generally when you feel the urge to copy
//-- paste chunks of code it should raise an
//-- alarm that you need to wrap the logic into
//-- a function...
//--
var core_curves = new List<Curve>();
for( var index = 0; index < count; index++ )
{
Curve[] curves;
Point3d[] points;
Rhino.Geometry.Intersect.Intersection.BrepPlane(
Core, planes[index], 0.0001, out curves, out points); //<-- CHANGED to CORE
//-- Complete Failure
//--
if( curves.Length == 0)
{
Print("Failed at Level " + index.ToString());
return;
}
//-- Numerical Issue or Topology Issue
//--
if( curves.Length != 1)
{
Print("Something is fishy at Level " + index.ToString());
}
core_curves.Add(curves[0]); //<-- CHANGED to CORE_CURVES
geometry.Add(curves[0]);
}
//-- To Produce an Excel Table
//-- Note: \t means tab and \r\n means new line (enter)
//--
var table = "Level\tFFL @ AGL(m)\tGEA(sqm)\tGIA(sqm)\tEfficiency(%)\r\n";
for( var index = 0; index < count; index++ )
{
//-- To Invert a signal (if too confusing, store each line in a
//-- list and invert the list.Reverse());
//-- All we are doing here is going from index: [0..count-1]
//-- to backwards: [count-1..0] so that the tabulated data
//-- are presented from top to bottom of the building
//--
//-- Now I will use backwards instead of index
//--
var backwards = count - index - 1;
var mass = mass_curves[backwards];
var core = core_curves[backwards];
//-- Look into documentation for: AreaMassProperties
//--
var mass_props = AreaMassProperties.Compute(mass);
var core_props = AreaMassProperties.Compute(core);
var mass_area = mass_props.Area;
var core_area = core_props.Area;
//-- This is WRONG because efficiency = NIA / GIA
//-- as an exercise you may compute first a ball park
//-- GIA by offsetting the GEA inbound by say 300mm
//-- and then remove the core from it to get a ball park NIA
//--
var efficiency = ( mass_area - core_area) / mass_area;
table += string.Format(
"{0}\t{1:0.000}\t{2:0.000}\t{3:0.000}\t{4:0.000}\r\n",
backwards,
planes[backwards].Origin.Z - 1.5, //-- Because cutting plane was +1.5 above FFL
mass_area,
mass_area - core_area,
efficiency);
}
//-- To Copy into Clipboard
//--
Clipboard.SetText(table);
//-- To Export into Grasshopper
//--
Excel = table;
//-- To Annotate a Section
//--
var annotxts = new List<string>();
var annopnts = new List<Point3d>();
for( var index = 0; index < count; index++ )
{
//-- To Move a Points 1.5m downwards
//--
var pnt = planes[index].Origin - Vector3d.ZAxis * 1.5;
var txt = string.Format("Level {0}\r\nFFL +{1:0.000} AGL", index, pnt.Z);
//-- And a nice section line
//--
var line = new Line(pnt, Vector3d.XAxis * 100);
geometry.Add(line);
annopnts.Add(pnt);
annotxts.Add(txt);
}
AnnoPnts = annopnts;
AnnoTxts = annotxts;
Geometry = geometry;
}
```

## Remarks

- The technique used here is a semi-organized approach to writing multi-phase procedures by storing interim results into collections. For a more complete approach to process structuring see the previous layout exercise which uses simple object-oriented approach.
- To decide whether to go for (a) Full spaghetti procedural representation, eg. highly nested loop constructs and computations of the fly, (b) Semi-structured representations, such as here or (c) Fully structured object-oriented representations… use the Litmus test(s): Does it fit in one page? Then use strategy (a); if not then, do you prefer to never write some thing again and again? Then use strategy (c); otherwise stick with (b).
- Generally speaking full structure comes with administrative overhead that does not justify the loss of intuition and mental complexity, unless there is a long term plan of reuse, other people that may be collaborating with you etc.
- For general design audiences where code quality and standards is not the primary consideration, the approach shown here is highly advisable.