As I have mentioned in other topics, I am developing a script for creating tool paths in Rhino. I know there are specialized plugins for that, but I prefer to do it this way.
The script is ready and works well on my Mac with Rhino 5.4.2, but the main purpose is to share it with a Windows V6 user, and we encountered some problems.
I have included an excerpt of my script here, together with a Rhino V6 file containing some of the problematic objects. Basically, you run the script, select a number of surfaces and an external (i.e. outside the surfaces) reference point, and the script creates the border curves initially, for both external and internal borders.
The external borders use the user defined reference point. For the internal borders I had to find a way to create a point inside the surface hole, and I chose to rotate a point around the curve end point in 8 steps until one was found inside the borders of the hole.
The test script pauses for a visual check to see if all border curves have been created. When acknowledged, it proceeds to offset the curves by a prescribed amount of 0.15 mm, and then terminates.
As I indicated, this works fine for my Mac and V5, but fails on some (not all) surfaces for Windows V6. I have searched for indicators to find a way to remedy this, but did not find any. I know some of the surfaces are upside down, i.e. with the back face up, but only one of those is problematic.
Well, offsetting has always been somewhat unreliable in Rhino. With the same object, an offset might succeed or not depending on the pick point. So using a common pickpoint for all objects is not always a great idea…
What I see in the maxtest1 file is that all the shapes which fail have a small loop in the pointy edge:
Depending on where the pick point is chosen, the offset either manages to go around that bad corner and succeed, or it fails and makes just a tiny offset at that spot.
My advice for offsets is as follows:
Offset both sides (inside and out) and then pick the outside offset (find some method) and discard the inside offset. If the parts are all “convex” the outer curve will be longer for example, and not have any points that lie on the surface. The best way to offset reliably is to use RhinoCommon, there is one method that does not require a pickpoint (like in GH). A + or - distance will offset in and out (but you do not know which is which, hence the test later). That way the pickpoint does not influence the result.
Thanks for your reply. Due to a slight communication error between me and my partner in this the attached test files were actually V5 Windows exports, not V6. But the problems remained, so it appears to be a Mac vs. Windows thing, irrespective of version.
But a later check on my Mac revealed that it too failed on two out of the three triangular surfaces.
I don’t have any experience with Rhino Common, so I don’t think I will get into that now, but I certainly will look at your alternative offsetting method with Rhinoscriptsyntax scripting.
Thanks again, have a Merry Xmas and a good 2020.
Cheers,
Max.
Unfortunately, Rhinoscriptsyntax does not offer that option, only single side offset based on a point for the direction. That is what I had scripted, so my only route seems to be Rhino Common. Hmmmmm…
Here is a rhinoscriptsyntax-style offset curve by distance function. - i.e. it works on object IDs, returns object IDs plus adds the result to the document. You will need to run it twice with positive and negative distances to get inside and outside offsets.
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
def OffsetCurveDist(crv_ID,plane,dist,style=1,tol=sc.doc.ModelAbsoluteTolerance):
crv=rs.coercecurve(crv_ID)
if style==0: trans=Rhino.Geometry.CurveOffsetCornerStyle.None
elif style==1: trans=Rhino.Geometry.CurveOffsetCornerStyle.Sharp
elif style==2: trans=Rhino.Geometry.CurveOffsetCornerStyle.Round
elif style==3: trans=Rhino.Geometry.CurveOffsetCornerStyle.Smooth
elif style==4: trans=Rhino.Geometry.CurveOffsetCornerStyle.Chamfer
offset=crv.Offset(plane,dist,tol,trans)
#offset could contain one or multiple curves or be None
if offset:
rc=[sc.doc.Objects.AddCurve(o_crv) for o_crv in offset]
sc.doc.Views.Redraw()
return rc
#test function
crv_ID=rs.GetObject("Select curve to offset")
dist=rs.GetReal("OffsetDistance?")
if crv_ID and dist:
offset_ID=OffsetCurveDist(crv_ID,rs.WorldXYPlane(),dist,1)
Thanks for your assistance, I have put your code to work and it works well, skipping over the pesky little loops generally. So far I found one exception, where one surface apparently had been trimmed improperly, leaving a small, zero width double line extending outwards.
What I also found is that the offset your code produces with a positive distance is always to the right when viewed in the curve direction.
Provided that the subject surface is the right way up, i.e. with the surface normal pointing upwards, this works out nicely with the DuplicateSurface function in Rhinoscriptsyntax, which produces counter-clockwise external border curves and clockwise internal border curves. So I skipped the double offsets and deleting the one on the surface.
I tried to find an easy way in rs. to check for surfaces with the wrong side up, and flip them before starting the rest of the procedure, but it got too complicated, so I will have to do a manual check before running the script.
As a potential benefit, the offset curve directions fit the preferred milling tool feed direction nicely to get the best (wood) cut quality. (not for laser cutting, the direction in which the burn front moves is not important)
Thanks again,
Max.
btw. I did not quite understand your comment in the code offset could contain one or multiple curves or be None, how can an offset of a single curve become multiple curves?
Hi guys , i am trying to offset one of the edges to make flaps to stick and make models…but when I use to offset some are offsetting inside and some outside … I want all the offset to be outside …any idea?
If it’s just one edge you’re referencing, it’s an open curve, and the offset side is ambiguous - it doesn’t know ‘inside’ from ‘outside’… However as you have relatively regular closed figures, perhaps you could get the outline of the whole figure, get the centroid of that, and create a vector from the midpoint of the side you want to offset to the centroid. That should give you a consistent (maybe) minus X-axis direction to create a plane - together with the previously gotten midpoint as the origin (Construct Plane). The plane can be to attached to the input to the offset curve component. You will probably need to invert (reverse) the minus X-Axis vector from above to offset to the outside.
I managed to get the vector in the direction of the offset …and constructed the plane with vector direction as x-axis but no results …or maybe I am missing a step to refer the direction of the offset may be ?
I tested this a little bit and there are a couple of subtleties - one is that how Rhino determines which direction the plane Z-Axis is facing looks like a bit random - so you need to add a component to guarantee that the Z-Axis faces towards you in all cases. I’ve attached a quickie test .gh below.
Another quick way of checking (non-scripted) which way a surface is facing is to use the shaded display mode with the backface color setting set to single color, and use an odd color for that setting.
In my example, they are planar curves, not surfaces, however I think if planar surfaces are made from those curves, the normals would face the same way. But again, this needs to be automated and not just visual on-screen.
It appears like that depends on how you select the closed curves. I drew two closed curves in opposite directions. If I select both to create the surfaces they ended up with the same Z-direction, if I select them one by one the Z-directions are opposite.