@sonderskovmathias
Check the attached. I broke up the logic in different methods so you can make your code scalable in the future. I am also not relying on any brep input, instead I am taking the data that is on each layer. Take note, that if you create a compiled version of this, the code will run much faster.
Concerning your ideas
1.To color the slabs, you have two options:
A. Create a list of colors for every slab from the corresponding layer. Output the colors from the component and do the normal preview routine,
B. Create a list of colors for every slab from the corresponding layer. Dont output the geometry, and instead override the display method.
- Determining child - parent relationships in layer can be a good homework for you to figure out. Hint… build a method, or perhaps more? to distill the logic and add this method in to what I called
Foo()
. Which you will, I hope… rename with a proper name which alludes to the action it is performing
Areascript.gh (38.5 KB)
private void RunScript(object x, ref object Slabs, ref object Areas, ref object LayerNames, ref object Data)
{
DataTree<double> outAreas;
DataTree<string> outLayerNames;
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
List<Brep> slabs = Foo(out outAreas, out outLayerNames);
sw.Stop();
Print(string.Format("Elapsed time: {0} ms", sw.ElapsedMilliseconds));
Data = ComputeData(outAreas, outLayerNames);
Slabs = slabs;
Areas = outAreas;
LayerNames = outLayerNames;
}
// <Custom additional code>
/// <summary>
/// Compute Geometrical data from Rhino Layers.
/// This method only works on Brep Geometry
/// </summary>
/// <param name="outAreas"></param>
/// <param name="outLayerNames"></param>
/// <returns></returns>
public List<Brep> Foo(out DataTree<double> outAreas, out DataTree<string> outLayerNames)
{
// This units stuff is not being used for now...
UnitSystem unitSystem = RhinoDocument.ModelUnitSystem;
string unitString;
double units = DetermineUnitSystem(unitSystem, out unitString);
DataTree<double> areas = new DataTree<double>();
DataTree<string> layerNames = new DataTree<string>();
List<Brep> slabGeo = new List<Brep>();
for (int i = 0; i < RhinoDocument.Layers.Count; i++)
{
string layerName = RhinoDocument.Layers[i].Name;
if (RhinoDocument.Layers[i].IsLocked) continue;
if (!RhinoDocument.Layers[i].IsValid)
throw new Exception(string.Format("Laeyer {0} is invalid", layerName));
// Get RhinoObjects in current Layer
Rhino.DocObjects.RhinoObject[] rhObjs = RhinoDocument.Objects.FindByLayer(layerName);
if (rhObjs == null || rhObjs.Length < 1)
throw new ArgumentNullException("You are attempting to access objects in an empty layer!");
for (int j = 0; j < rhObjs.Length; j++)
{
if (rhObjs[i] == null)
throw new ArgumentNullException(string.Format("object at index {0} in Layer {1} is null", j, layerName));
// You might want to check if its a valid GUID
Rhino.DocObjects.RhinoObject rhObj = RhinoDocument.Objects.Find(rhObjs[j].Id);
// Get geometry base
Rhino.Geometry.GeometryBase rhGeo = rhObj.Geometry;
Brep brep = null;
if (rhGeo.HasBrepForm) brep = Brep.TryConvertBrep(rhGeo);
else
throw new Exception(string.Format("Geometry object at index {0} in Layer {1}" +
" cant be converted to a Brep", j, layerName)); // throw or continue??
if (!brep.IsValid)
throw new Exception(string.Format("Brep at index {0} in Layer {1} is not valid", j, layerName)); // throw or continue??
if (!brep.IsSolid)
throw new Exception(string.Format("Brep at index {0} in Layer {1} is not solid", j, layerName)); // throw or continue??
if(brep != null)
{
Brep slab = GetLowestBrepFace(brep);
double floorArea = slab.GetArea() * 0.0000010;// converts to square meters
areas.Add(floorArea, new GH_Path(i));
layerNames.Add(layerName, new GH_Path(i));
slabGeo.Add(slab);
}
}
}
outAreas = areas;
outLayerNames = layerNames;
return slabGeo;
}
/// <summary>
/// Display data
/// </summary>
/// <param name="areas"></param>
/// <param name="layerNames"></param>
/// <returns></returns>
public List<string> ComputeData(DataTree<double> areas, DataTree<string> layerNames)
{
DataTree<double> totalAreas = new DataTree<double>();
double totalArea = 0;
for (int i = 0; i < areas.Branches.Count; i++)
{
double totalA = 0;
for (int j = 0; j < areas.Branches[i].Count; j++)
totalA += areas.Branches[i][j];
totalArea += totalA;
totalAreas.Add(totalA, new GH_Path(i));
}
List<string> data = new List<string>();
for (int i = 0; i < totalAreas.Branches.Count; i++)
{
for (int j = 0; j < totalAreas.Branches[i].Count; j++)
{
data.Add(string.Format("{0,-20} \t: {1,15:n1} m2 ",
layerNames.Branches[i][j], totalAreas.Branches[i][j]));
data.Add(Environment.NewLine);
}
}
data.Add(string.Format("Total {0,-13} \t: {1,15:n1} m2 ", "", totalArea));
return data;
}
/// <summary>
/// Determine the current Unit system of the Rhino
///Doc
/// </summary>
/// <param name="unitSystem"></param>
/// <param name="_sUnits"></param>
/// <returns></returns>
public double DetermineUnitSystem(UnitSystem unitSystem, out string _sUnits)
{
double units = 0;
string sUnits = "";
switch(unitSystem)
{
case UnitSystem.Millimeters: units = 1000; sUnits = "mm2"; break;
case UnitSystem.Meters: units = 1; sUnits = "m2"; break;
// Keep going
}
_sUnits = sUnits;
return units;
}
/// <summary>
/// Get Lowest Brep surface from a Brep Solid
/// </summary>
/// <param name="brep"></param>
/// <returns></returns>
public static Brep GetLowestBrepFace(Brep brep)
{
Brep lowest = null;
for (int i = 0; i < brep.Faces.Count; i++)
{
BrepFace face = brep.Faces[i];
Brep surface = brep.Faces.ExtractFace(i);
Plane frame;
if(!face.FrameAt(0.5, 0.5, out frame))
if (frame.ZAxis.Z < 0)
lowest = surface;
}
return lowest;
}