I have a script works well in Rhino6, but when I run it in Rhino 7, the offsetcurve works differently, I have give the direction with the centroid area point to make as inside curve, however, it still offset the curve in y axis, I also try vector method, it still works wrong. what is the problem?
The script:
import rhinoscriptsyntax as rs
winFraWid=100
zxPlane=rs.WorldZXPlane()
rec=rs.AddRectangle(zxPlane,2000,1000)
winPts=rs.CurvePoints(rec)
cenPt=rs.CurveAreaCentroid(rec)[0]
vec=rs.VectorCreate(winPts[0],cenPt)
inFrameRec=rs.OffsetCurve(rec,cenPt,winFraWid,normal=vec)
Hi @herocaripod ,
import rhinoscriptsyntax as rs
winFraWid = rs.GetInteger("Offset value")
curve_id = rs.GetObject("Select a curve", rs.filter.curve)
if curve_id:
# Get the plane of the selected curve
curve_plane = rs.CurvePlane(curve_id)
if curve_plane:
winPts = rs.CurvePoints(curve_id)
cenPt = rs.CurveAreaCentroid(curve_id)[0]
# Calculate the offset direction vector
vec = rs.VectorCreate(cenPt, winPts[0])
vec = rs.VectorUnitize(vec)
# Offset the curve using the direction vector
inFrameRec = rs.OffsetCurve(curve_id, vec, winFraWid)
else:
print("Failed to get the plane of the selected curve.")
else:
print("No curve selected.")
You must set reference plane for the offset, in this case we extract the plane from the curve using CurvePlane.
Hope this helps,
Farouk
yes, i try this program in Rhino 7, the result is still this.
still thank you!
it seems like the point with vector cannot give rhino a clear direction
The problem is that getting the correct direction point is not an easy task. The curve area centroid could actually be outside the curve for example. And as offset is sometimes sensitive to exactly where the offset point is placed, I prefer a different approach. I offset both sides using the simple distance overload in RhinoCommon, then I try to determine which is inside from the two results. I’m pretty sure that the inside offset will always have a smaller area then the outside offset - in any case that is what I use here.
Also note that offset can produce multiple results…
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
def GetCombinedArea(crvs,tol):
tot_area=0
for crv in crvs:
mp=Rhino.Geometry.AreaMassProperties.Compute(crv,tol)
if not mp: return
tot_area+=mp.Area
return tot_area
def OffsetCrv2Sides(crv,plane,dist,trans,tol):
offset1=crv.Offset(plane,dist,tol,trans)
offset2=crv.Offset(plane,-dist,tol,trans)
#either offset could be a list of one or multiple curves or be None
return offset1,offset2
#planar closed curves filter
def cp_crv_filt(rhino_object, geometry, component_index):
return rs.IsCurvePlanar(geometry) and rs.IsCurveClosed(geometry)
def OffsetClsdCrvInside():
msg="Select a closed planar curve to offset inside"
crv_id = rs.GetObject(msg,4,preselect=True,custom_filter=cp_crv_filt)
if not crv_id: return
tol=sc.doc.ModelAbsoluteTolerance
dist=rs.GetReal("Distance to offset?",1,minimum=tol)
if dist is None: return
crv=rs.coercecurve(crv_id)
rc,plane=crv.TryGetPlane()
if not rc:
print("Error getting curve plane")
return
#change the following if necessary
trans=Rhino.Geometry.CurveOffsetCornerStyle.Sharp
off_1,off_2=OffsetCrv2Sides(crv,plane,dist,trans,tol)
if off_1 is None or off_2 is None:
print("Unable to get offsets")
return
off_1_area=GetCombinedArea(off_1,tol)
off_2_area=GetCombinedArea(off_2,tol)
if not off_1_area or not off_2_area:
print("Unable to calculate areas")
return
#if you want an outside offset, change < to >
if off_1_area<off_2_area:
offset_ids=[sc.doc.Objects.AddCurve(crv) for crv in off_1]
else:
offset_ids=[sc.doc.Objects.AddCurve(crv) for crv in off_2]
rs.SelectObjects(offset_ids)
sc.doc.Views.Redraw()
OffsetClsdCrvInside()