Offsetting Surface borders - script fails on Rhino V6 for windows but not on V5 for Mac?

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.

Can somebody help me find the cause?

Max. (1.8 KB)

maxtest1.3dm (439.3 KB)

maxtest2.3dm (787.9 KB)

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.

However, you are still likely to have occasional failures. That is unfortunately “just the way it is”…

Hi Mitch,

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.

Seems odd, as within the same version (V5 or V6) regardless of platform, it should be calling the same geometry functions.

I would first look into how those microloop corners are being produced - that shouldn’t happen.

i gues it is my fault certain parts are just flattened surfaces , but other parts are not and that is a bit strange,

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…

Yep… unfortunately.

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):
    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 could contain one or multiple curves or be None
    if offset:
        rc=[sc.doc.Objects.AddCurve(o_crv) for o_crv in offset]
        return rc

#test function
crv_ID=rs.GetObject("Select curve to offset")
if crv_ID and dist:

Hi Mitch,

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,

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?

Like this…

Ah yes, of course…

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 ?

now i need to figure how to use vector direction as the direction of the offset

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. (11.3 KB)

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.

Edit: I’m on V5 for Mac.

OK, interesting…