Hi All,
I have a grasshopper VB script which creates a closed polyline and I was hoping for some advise on how to extract the area.
I noted this link: Area of closed polyline which suggests the AreaMassProperties don’t work on a polyline - but i’m not sure what would? (or how to get my shape without a polyline…)
In a nut shell workflow is as follows:
- I run an iterative calculation, exporting a series of planar points representing a force area.
- I create a closed, planar polyline with those points.
- I want to extract the area and centroid of the closed polyline.
Important section of code is as follows:
' Generates the closed polyline.
Dim PolyPts as New List (of Point3D)
PolyPts.add(USBsPt)
PolyPts.add(PtB)
'PolyPts.add(PtX)
PolyPts.add(PtD67)
PolyPts.add(PtD)
PolyPts.add(DSBsPt)
PolyPts.add(USBsPt)
Dim Poly as new polyline (PolyPts) - WORKING UPTO HERE
' Calculates Area, centroid and Moments
UpArea = Rhino.Geometry.areamassproperties.compute(Poly,.001) - Not Working.
Could anyone advise on a workaround for this? Potentially convert to a brep, mesh or use some other Rhino Function?
Any help would be much appreciated
You can triangulate it and compute the triangle areas. Here’s a Python script demonstrating how:
Thanks Anders, i will have a look at that tomorrow. I did start with calculating sub areas/centroids so I may be better to fall back on that.
Are there any other methods to extract a polyline area - or potentially mesh or generate a patch surface that the areamassproperties would operate on?
Cheers
A simple method would be to convert it to a curve using Polyline.ToNurbsCurve
and then using AreaMassProperties.Compute
to compute the area. I think the method in the script I linked to is plenty simple though, but it of course depends
Thanks Anders - that’s very helpful
Your method is straight forward, I agree. My - complication - is that my polyline is an amalgamation of upto 10 points, and these can change.
The project is using grasshopper to iterate an ‘uplift’ profile on a concrete dam.
I can independently set upstream load, downstream load, drain locations and effectiveness - then you have ‘cracking’ if the loads are to high.
As a result to triangulate I either need a whole series of If statements subject to which points are ‘true’ for a given run… or I can be lazy and build a polyline then convert to nurbs
I’ll give it a go now, and confirm if it all works
I do have another question, as some of my control points are identical in some circumstances - is there an easy way in VB to cull duplicates - like Rhino.geometry.Point3D.CullDuplicates?
I tried the above, and i’ve had some success (embedded in polyline component for example) - however I cant seem to create a new list, being the culled list?
Any advice would be appreciated.
Thanks again Anders, that worked a treat.
I declared a new Curve - then assigned that to Poly.ToNurbsCurve.
For any who come later final code (or at least the important bits):
' Declare Variables
Dim PolyPts as New List (of Point3D)
Dim Poly as polyline
Dim NrbCrv as NurbsCurve
' Adds points into the 3D Points array
PolyPts.add(USBsPt)
PolyPts.add(PtB)
' PolyPts.add(PtX)
PolyPts.add(PtD67)
PolyPts.add(PtD)
PolyPts.add(DSBsPt)
PolyPts.add(USBsPt)
' Creates PolyLine
Poly = new Polyline(PolyPts)
' Convert Polyline to Nurbs
NrbCrv=Poly.ToNurbsCurve
'Compute area and assign to output LDiag
LDiag = Rhino.Geometry.areamassproperties.compute(NrbCrv,.001).Area
1 Like
That would be one way, but the polyline class itself actually has several methods that sounds like they might be relevant to your modelling goals. Notably:
Glad it worked
Thanks again Anders. With the way I am running my iterations, turned my version using point transforms, polylines and the mass commands is running to slow (1 second per solution - but this is part of what I intend to be a ‘live’ design package (for concept design upgrades on concrete dams) so i’ve had to re-write.
To speed things up i’ve dropped back to calculating areas. Managed to cut it back to two distinct geometry types and effectively breaking into rectangular or triangular sections - then calculating areas and centroids to take a moment and calculate a resultant.
For anyone else doing something similar in future - options I’m trying to calculate area centroids for i’ve simplified back to:
With Variables linking back to zones:
ZxA (Zone X Area)
ZxO (Zone X Centroid)
ZxM (Area moment of Zone X about PtA)
Code is as follows:
if Xx < Gx then ' Code for cracking US of the line of the drains. Output ResX verified for all possible Xx (At Heel, halfway to drain, at drain).
' Calculates drain function positions
D0y = By + (Gx-Xx)*math.tan(math.atan((Dy-Xy)/(Dx-Xx)))
if D0y > D100y then D100y = D0y ' Adjusts the drains 100% functional position if water level is less than drain head.
D67y = D100y - (1-DrnEff/100)*(D100y - D0y)
' Calculates areas for each sub-area
Z1A = (Ay-By)*(Xx-Ax)
Z2A = (Ay-D67y)*(Gx-Xx)
Z3A = (Cx-Gx)*(Cy-Dy)
Z4A = (Dx-Gx)*(Dy-D67y)/2
Z5A = (D67x-Xx)*(D67y-By)/2
' Calculates Offsets for each sub-area
Z1O = B -(xx-Ax)/2
Z2O = B - (Xx-Ax) - (Gx-Xx)/2
Z3O = (Cx-Gx)/2
Z4O = (Dx-Gx)*2/3
Z5O = (Cx-Gx)+2*(Gx-Xx)/3
else ' Code for cracking DS of the line of the drains.
' For this case, the crack extends past the drains and it is assumed the drains do not function.
' Calculates area of each sub-area
Z1A = (Ay-By)*(Xx-Bx)
Z2A = (Cy-Dy)*(Cx-Xx)
Z3A = (Dx-Xx)*(Dy-Xy)/2
Z4A = 0
Z5A = 0
' Calculates offsets for each sub-area
Z1O = B-(xx-Ax)/2
Z2O = (Cx-Xx)/2
Z3O = 2/3* (Dx-Xx)
Z4O = 0
Z5O = 0
end if
' Calculates Moments about toe for uplift
Z1M = -Z1A*Z1O
Z2M = -Z2A*Z2O
Z3M = -Z3A*Z3O
Z4M = -Z4A*Z4O
Z5M = -Z5A*Z5O
’ Calculates resultant area and area moment for uplift.
' Calculates Sum of Vertical Forces for Uplift
SumFU = -(Z1A + Z2A + Z3A + Z4A + Z5A)
' Calculates sum of area moments for Uplift
SumMU = (Z1M + Z2M + Z3M + Z4M + z5M)
' Determines Resulting Location for Uplift
ResXU = SumMU/SumFU