Good morning everyone,
I’m currently working on something, where I’d like to make use of the rhinoinside for python from Rhino 7.
-
What do I want to do
Modelling a 2D - NURBS - Curve starting from the cartesian origin at (0.00,0.00), going on in the (x,y)-plane and integrating it from x = 0 to a variable upperBound x to get the area and the centroid (1st moment). A *.gh script is attached for reference. integrateNurbsCurveFromZeroToUpperBound.gh (17.2 KB) -
How do I do it
Since RhinoCommon only provides AreaMassProperties for closed curves, the intersection of a vertical Line at the upperBound x starting from the x - axis with the NURBS curve is computed via an optimization problem. While I am totally aware of the CurveLineIntersection capabilities of RhinoCommon, this is the easier way for this application. After determining the point of intersection and projecting it down to the x-axis, a horizontal Line from the origin to the upperBound is created. The NURBS - Curve is trimmed after obtaining the curve parameter, where the intersection takes place. All Curves are put into a list and joined subsequently, allowing me to obtain the moments. -
Where is the problem?
While above mentioned approach works for polynomial degree = 1 perfectly fine, the joinCuves() method does not seem to work properly when degree > 1 returning an empty array. Hence computing the AreaMassProperties fails. The point of Intersection on the curve still seems correct, but joining fails. -
Remarks on the code attached
- Strain is the x - axis, Stress is the y - axis, parametricStrain is the curve parameter
- Intersection is computed with scipy and brentq()
- Run it with degree = 1, it returns the correct area = 2.5 for integration between 0 and x = 2.00
- Run it with degree = 2, it returns print(‘areaMassProperties.Area:\t\t’,areaMassProperties2.Area) AttributeError: ‘NoneType’ object has no attribute ‘Area’
- What would I like to know?
- What is the best way to compute an area and its centroid for an open curve?
- What am I doing wrong at the joining operation?
- How to improve the code regarding computational efficiency?
import rhinoinside
rhinoinside.load()
import System
import Rhino.Geometry as rg
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize as opt
import datetime
plt.close('all')
x = [0.00, 1.00, 2.00, 3.0, 4.0, 5.0]
y = [0.00, 2.00, 1.00 ,15.0, 10.0, 20.0]
pointCount = 5
degree = 1 #change this to 2
nc = rg.NurbsCurve(dimension = 2, rational = True, order = degree + 1, pointCount = pointCount)
numAllKnots = pointCount + degree - 1
numExtKnots = degree
numIntKnots = numAllKnots - 2 * degree
didSucceed = nc.Knots.CreateUniformKnots(1/(numIntKnots+1))
for k in nc.Knots:
print(k)
for i in range(nc.Points.Count):
nc.Points.SetPoint(index = i, x = x[i], y = y[i], z = 0.0)
nc.Points.SetWeight(index = i, weight = 1.0)
print('nc.Domain.Min:\t', nc.Domain.Min)
print('nc.Domain.Max:\t', nc.Domain.Max)
print('nc.IsValid:\t', nc.IsValid)
print('nc.SpanCount:\t', nc.SpanCount)
t = np.linspace(nc.Domain.Min, nc.Domain.Max,101)
for i in t:
pt = nc.PointAt(t = i)
plt.scatter(x = pt.X, y = pt.Y)
#----------------------------------------------------------------------
def getParametricStrain(realStrain):
def checkParametricStrain(assumedParametricStrain):
return realStrain - nc.PointAt(assumedParametricStrain).X #realStrainResidual
parametricStrain = opt.brentq(checkParametricStrain, a = nc.Domain.Min, b = nc.Domain.Max)
return parametricStrain
#------------------------------------------------------------------------
realStrain = 2.00
parametricStrain = getParametricStrain(realStrain)
residualStrain = realStrain - nc.PointAt(parametricStrain).X
realStress = nc.PointAt(parametricStrain).Y
currentDomain = rg.Interval(0.0,parametricStrain)
currentNurbsCurve = nc.Trim(currentDomain)
pointOnCurve = rg.Point3d(realStrain,realStress,0.0)
projectedPoint = rg.Point3d(realStrain,0.0,0.0)
origin = rg.Point3d(0.0,0.0,0.0)
auxVertical = rg.LineCurve(pointOnCurve, projectedPoint)
auxHorizontal = rg.LineCurve(projectedPoint, origin)
crv = System.Collections.Generic.List\[rg.Curve\]()
crv.Add(currentNurbsCurve)
crv.Add(auxVertical.ToNurbsCurve())
crv.Add(auxHorizontal.ToNurbsCurve())
joinedCurve = rg.Curve.JoinCurves(crv)
areaMassProperties2 = rg.AreaMassProperties.Compute(joinedCurve, area = True, firstMoments = True, secondMoments = False, productMoments = False)
print('----------------------------------------------------------------------')
print('areaMassProperties.Area:\t\t',areaMassProperties2.Area)
print('areaMassProperties.AreaError:\t\t',areaMassProperties2.AreaError)
print('areaMassProperties.Centroid:\t\t',areaMassProperties2.Centroid.X)
print('areaMassProperties.CentroidError:\t',areaMassProperties2.CentroidError.X)
print('----------------------------------------------------------------------')