A bug in AddRevSrf?

Hi,

I appear to have run into a bug in AddRevSurf. Here is how to reproduce: open badRevolveExample.3dm (28.1 KB). Then run the following script, which creates (what should be) the same revolved surface via a macro and via AddRevSrf, and a simple sphere.

Now if you try to eg BooleanSplit the sphere with the surface created via the macro, it works fine. However, if you try the same thing using the surface generated by AddRevSrf, the split fails - the surface appears to have some subtle issue.

Is this a bug or am I missing something?

Thanks a lot,
Egor

import rhinoscriptsyntax as rs

revline=rs.ObjectsByName("_revline")

# create a revolved surface via AddRevSrf
axis=rs.AddLine([0,0,0],[0,0,1])
surf1=rs.AddRevSrf(revline,axis)
rs.ObjectLayer(surf1,rs.AddLayer("AddRevSrf"))

# create another via a macro
rs.Command("SelNone")
rs.SelectObject(revline)
rs.Command("Revolve 0 Enter Enter Enter SelNone SelLast")
rs.UnselectObject(revline)
surf2=rs.SelectedObjects()
surf2=surf2[0]
rs.ObjectLayer(surf2,rs.AddLayer("macro"))

sphere=rs.AddSphere([0,0,0],20)

Interesting. SelDup selects the two revolved surfaces as identical, but Properties>Details says that the surface created by AddRevSrf is a “surface of revolution” and the surface created by the macro is a “rational NURBS surface”. The intersector finds a valid intersection curve in both cases, but the curve fails to split the revolved surface. Pulling the intersection curve to the revolved surface produces a funny result. Hmmm…

Edit - if I convert the surface of revolution to a NURBS surface by moving one control point out a bit and then back the same distance, the split works…

–Mitch

Rhino’s Revolve command creates Nurbs surface due to some difficulty in calculating closest points on surfaces of revolution. The rs.AddRevSrf function should do the same - I’ve reported this as a bug.

This version of rs.AddRevSrf should work better for you.

import math
import Rhino
import rhinoscriptsyntax as rs
import scriptcontext

def AddRevSrfEx(curve_id, axis, start_angle=0.0, end_angle=360.0):
    curve = rs.coercecurve(curve_id, -1, True)
    axis = rs.coerceline(axis, True)
    start_angle = math.radians(start_angle)
    end_angle = math.radians(end_angle)
    srf = Rhino.Geometry.RevSurface.Create(curve, axis, start_angle, end_angle)
    if not srf: return scriptcontext.errorhandler()
    ns = srf.ToNurbsSurface()
    if not ns: return scriptcontext.errorhandler()
    rc = scriptcontext.doc.Objects.AddSurface(ns)
    scriptcontext.doc.Views.Redraw()
    return rc

http://mcneel.myjetbrains.com/youtrack/issue/RH-31805

Dale,

thanks a lot, that one works! :wink:

Would you by any chance also have a code snippet to fix this issue? Ran into it myself and also having to workaround via a macro…

Thanks a lot,
E.

@ZmeiGorynych, the problem in your link seems to be fixed already. Do you see this not working on trimmed surfaces ? Below example is identical to the code rs syntax is using:

import Rhino
import rhinoscriptsyntax as rs
import scriptcontext

def OffsetSrf(distance, tolerance=None, both_sides=False, create_solid=False):
    brep = rs.coercebrep(id, True)
    face = None
    if (1 == brep.Faces.Count): face = brep.Faces[0]
    if face is None: return scriptcontext.errorhandler()
    if tolerance is None: tolerance = scriptcontext.doc.ModelAbsoluteTolerance
    newbrep = Rhino.Geometry.Brep.CreateFromOffsetFace(
                face, distance, tolerance, both_sides, create_solid)
    
    scriptcontext.doc.Objects.AddBrep(newbrep)
    scriptcontext.doc.Views.Redraw()
    
if __name__=="__main__":
    id = rs.GetObject("surface to offset", 8, True, False)
    if id:
        OffsetSrf(distance=10, both_sides=False, create_solid=True)

c.

@clement,

here is the issue I see, working with badOffsetExample.3dm (475.5 KB)

The call to OffsetSurface returns None, while the macro works fine.

I got Rhino off the website less than a month ago, so the code there should be up to date.

import rhinoscriptsyntax as rs

srf=rs.ObjectsByName("test")
# This call fails
offsetSrf=rs.OffsetSurface(surface_id=srf,distance=2,create_solid=True)
# This one succeeds
rs.Command("_SelNone")
rs.SelectObject(srf)
rs.Command("_OffsetSrf _Distance 2 _Enter")
rs.Command("_SelLast")
tmp=rs.SelectedObjects()

@ZmeiGorynych,

is understand now. You`re offsettings a polysurface instead of a surface. Usually this is done using rs.OffsetBrep() but this is not implemented yet in RhinoScript syntax.

c.

If you are using the Rhino WIP, you can write your own version of RhinoScript’s OffsetBrep method by calling Rhino.Geometry.Brep.CreateOffsetBrep.

Dale,

thanks! How can I download the WIP? I found this link, but when I click on the big Download button there, I end up here, where I can’t see any link to the WIP.

Best,
E.