Offset surface on predefined side

Hello,

I’m writing a plugin that should unroll sheet metal part (closed polysurface) by mid-surface.
Mid-surface is located at half thickness of the part and I need to create this surface somehow.
I have an idea to create it by offsetting the largest surface within polysurface for half of the thickness.
Each side of my part is a single surface, so the largest surface is an outside “shell”

I came to the point where I need to implement the offset command on this surface but I don’t know how to “tell it” exactly on which side I need the offset.

I’m working in python

Aleksandar

Maybe you can offset both sides, compare the two resulting surfaces and use the smallest. On the other hand, if you have a closed polysurface, the normals are facing outward, so you need the offset to be negative

For example (btw: no checks if it is unrollable):

import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc


def unrollSheet():
    poly=rs.GetObject("Select sheet to unroll",rs.filter.polysurface)
    if poly==None:
        return
    thickness=rs.GetReal("Enter sheet thickness",3,1,20)
    if thickness==None:
        return
    poly=rs.coercebrep(poly)
    surfaces=poly.Faces
    area=0
    for srf in surfaces:
        mp=Rhino.Geometry.AreaMassProperties.Compute(srf)
        area_temp=mp.Area
        if area<area_temp:
            area=area_temp
            new_srf=srf
    offset=new_srf.Offset(-thickness,0.01)
    unroll = Rhino.Geometry.Unroller(offset)
    breps, curves, points, dots = unroll.PerformUnroll()
    rc = [sc.doc.Objects.AddBrep(brep) for brep in breps]
    sc.doc.Views.Redraw()

unrollSheet()

Thank you very much for the hint.

I have closed polysurface 99.99% of the time so negative half thickness offset gives me the the midsurface that I need to develop.
For the remaining 0.01% i will do the both side offset ant take the smaller surface
(currently not implemented in the script bellow )

For some reason your example unrolls the “untrimmed version” of the surface.

anyhow, here is my current version of the test script:

import rhinoscriptsyntax as rs

def TestExpander():

# Input 

part = rs.GetObject("Select part for expansion" , rs.filter.polysurface or rs.filter.surface )
if part is None:
    print ("Nothing Selected")
    return
thickness=rs.GetReal("Enter sheet thickness",3,1,20)
if not thickness:
    return
    
# Find largest surface

arrSrfs = rs.ExplodePolysurfaces(part)
if not arrSrfs:
    # single surface selected
    theSurface = part
else:    
    areaMax=0
    theSurface = None
    for srf in arrSrfs:
        tempSrf=rs.SurfaceArea(srf)
        if tempSrf>areaMax:
            areaMax = tempSrf
            theSurface = srf
if not theSurface:
    print "no surface found!"
    return
offset = rs.OffsetSurface(theSurface,-thickness/2)
if not offset:
    print "error offseting"
    return
unRolled = rs.UnrollSurface(offset)
if not unRolled:
    print "error unrolling"
    return 
    
# CleanUp temporary objects

if arrSrfs:
    rs.DeleteObjects(arrSrfs)
if offset:
    rs.DeleteObject(offset)
    
if __name__=="__main__":
    TestExpander()

I had to dive into RhinoCommon a bit deeper to understand what’s happening when working with polysurfaces faces and why it gave back the untrimmed surface. The script below does return the trimmed version of your surface.
What I like about doing it through use of rhino common is that the script performs actions on Rhino objects without the need to ‘bake’ them to the scene. This prevents you from doing the cleanup of unwanted geometry at the end of the script.
import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc

def unrollSheet():
    poly=rs.GetObject("Select sheet to unroll",rs.filter.polysurface)
    if poly==None:
        return
    thickness=rs.GetReal("Enter sheet thickness",3,1,20)
    if thickness==None:
        return
    poly=rs.coercebrep(poly)
    faces=poly.Faces
    area=0
    for face in faces:
        mp=Rhino.Geometry.AreaMassProperties.Compute(face)
        area_temp=mp.Area
        if area<area_temp:
            area=area_temp
            new_face=face
    distance = -thickness/2
    tolerance = sc.doc.ModelAbsoluteTolerance
    both_sides=False
    create_solid=False
    offset = Rhino.Geometry.Brep.CreateFromOffsetFace(new_face, distance, tolerance, both_sides, create_solid)
    unroll = Rhino.Geometry.Unroller(offset)
    breps, curves, points, dots = unroll.PerformUnroll()
    srfs = [sc.doc.Objects.AddBrep(brep) for brep in breps]
    sc.doc.Views.Redraw()

unrollSheet()