Hey guys,
I have just started building my very first Grasshopper component and have no experience C#. To start slowly, I want to replace my visual GH script with a custom C# component, step by step replacing GH components on my canvas until I finally only have one custom component instead of a cluster.
Obviously I stumbled across my first error:
- I can’t manage to generate the boundary polyline curves from the breps I input
- I do not retrieve the same Centroids like the GH components
Do you guys know why this might be the case?
Best
Max
Here is the Code:
protected override void SolveInstance(IGH_DataAccess DA)
{
List inputBreps = new List();
if (!DA.GetDataList(0, inputBreps)) return;
List<PolylineCurve> boundaries = new List<PolylineCurve>();
List<Point3d> centroids = new List<Point3d>();
foreach (Brep brep in inputBreps)
{
if (brep != null)
{
// Retrieve the boundary curves and concatenate them into a single polyline curve
Curve[] edgeCurves = brep.DuplicateEdgeCurves();
PolylineCurve boundary = new PolylineCurve();
boundary.MakeClosed(0.001); // Close the polyline to ensure it's a closed boundary
boundaries.Add(boundary);
// Calculate the centroid
Point3d centroid = brep.GetBoundingBox(true).Center;
centroids.Add(centroid);
}
}
DA.SetDataList(0, boundaries);
DA.SetDataList(1, centroids);
}
GH has access to most of RhinoCommon, right?
This doesn’t get the centroid of the brep. It puts a bounding box around the brep, and then gets the centroid of the box.
What you probably want is:
VolumeMassProperties foo = VolumeMassProperties.Compute(brep);
and then foo.Centroid.X is the center in the x axis, etc.
Do you need to duplicate them? Can you just loop over .Edges for whatever calculation you want?
The story is much bigger, but I thought I should go step by step. The cluster that I have created takes two surfaces (The “Ceiling” of a lower floor & the “Floor” of the upper floor (I am taking about a building)) and than checks where they overlap ->cuts them and stores the surfaces on the respective layers (“Roof”, “Exposed Floor”, “Internal Floor”)
FloorCheck_Visuell.gh (25.9 KB)
I have attached the file.
Technically I also want to repeat this checking for as many floors that I have in the file, currently I just multiplied the component and connected the intersecting surfaces manually.
I jsut didn’t want to overload my request and start with little questions.
Then hopefully you got what you wanted, because I don’t understand exactly what you’re doing (not that I need to).
Connected on and off, just checking in when the access is good.
No worries. The centroid no works exactly like the other GH components. I used the AreaMassProperties as my beeps are planar surfaces all the time. So thank you!
For the polyline curve I am still not sure what to do. I need them as a geometry. What do you mean with Looping?
Best
Max
Looping is also in the workshop videos, I think it’s part 2 or so. Generally it just describes an looping operation that is done until a certain condition is met.
You are not actually connecting the brep.edges (edgeCurves) you copied anywhere in your code to a polyline (I recommend working with polycurves btw). Working with arrays (Curve[ ]) is kinda finicky, I usually just make a new list and add them through list.addrange() to work with them.
I didn’t really know what you were doing with this:
and whether you really needed to create a set of copies, or whether you were looking at curve properties and could just
Foreach
over the existing edges to look at them.
Given your additional explanation, I think I understand that you do want a unified curve around the floor of the building as a separate object.
Yes my current task is super simple, which is why I am confused the writing it in C# makes it so complicated. I have two surfaces, and for each surface I need to retrieve the boundary curve. So I get two closed polylines. For now thats just my task. Obviously I will use that in many different ways, but I want to implement my bug cluster “component by component” to keep track of what I am doing.
Glad to hear you’ve moving on, I think how you’d want to get your previous code working is this:
Note I haven’t tested this code, but it should get you going in the right direction. I included comments where I made changes.
protected override void SolveInstance(IGH_DataAccess DA)
{
List inputBreps = new List();
if (!DA.GetDataList(0, inputBreps)) return;
// Use a Curve List Here
List<Curve> boundaries = new List<Curve>();
List<Point3d> centroids = new List<Point3d>();
foreach (Brep brep in inputBreps)
{
if (brep != null)
{
// Retrieve the boundary curves and join them into curves
Curve[] edgeCurves = brep.DuplicateEdgeCurves();
// Notice that this is another array.
// If a brep has inner cut outs, it will have multiple loops
Curve[] joinedEdgeCurves = new Curve.Join(edgeCurves);
// By definition, edges from a valid brep must be closed,
// so it's probably safe to just assume that they're closed here
boundaries.AddRange(joinedEdgeCurves);
// Calculate the centroid
Point3d centroid = brep.GetBoundingBox(true).Center;
centroids.Add(centroid);
}
}
// If you needed your centroids and boundaries to be in a one-one structure,
// you'd need to either filter out any inner loop when we're joining edge curves
// or you'd want to set up a datatree.
DA.SetDataList(0, boundaries);
DA.SetDataList(1, centroids);
}
See https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.curve/joincurves for additional info on JoinCurves. Your code wasn’t using the edge curves you’d gotten from the brep for anything, it was instead just initializing a new PolylineCurve without adding any curves to it. @Tuyen_Nguyen got it right when he pointed out that you weren’t joining the curves together.