Offset surface one vector

Hi,

Is it possible to offset a surface in such way that every section in one vector is the exact given dimension?

I see what you mean, I think… As an example the radius of a sphere would get smaller but the perimeter of the shape shown would stay the same and not shrink as it was offset?

The only way of doing this that I can think of is extruding the outline of the shape perpendicular to the offset direction and then untrimming or extending the surface you’ve offset and then intersecting/trimming the results.

Can it be as simple as …Extrude the surface in that direction… is that what you mean?

-Pascal

Nope, with an extrusion de section true the body will not be the same.

I will explain the purpose.
Let’s say we have a doubly curved shell with ribbons. The exact depth of the ribbons must be 200mm in the yz vector.
To speed up the process and work with history, we create a body, a 200mm thicken of the shell in yz direction. We create 20 sections (yz) true the body and voila we have the outline of the ribbons.

any idea?

Edit: this is a function of NX, another (not our preferred) program, called a Variational Sweep

Hi Thomas- I guess you could project lines to the base surface and extrude these vertically 200 units? if the outer edge of the ‘ribbons’ must correspond to an offset of the original shape this will not work- the outer edge will be the same as the starting curve. - I don’t know if this is it, maybe:

Extrude.3dm (115.0 KB).

-Pascal

Hi Pascal,

The end goal is to create a more complex slice/thicken/offsetsrf to create the stiffening on a surface. As shown in the example, the (offset) height of the (green solids) stiffening is always 250mm. So projecting should work followed by offsetting the curve and the loft by example.
But what I am trying to accomplish is to create a more complex slice of 250mm thick on the surface, which I can section in one direction with the exact frame height.

It’s hard to explain, so I hope it makes sense…
create frames.3dm (3.8 MB)

I suppose you can section the surface then from a view/CPlane normal to the desired offset, offset the resulting curves, then create a lofted or planarSrf.

create frames_PG.3dm (112.7 KB)

-Pascal

Yes! Haha, I did exactly what you suggested in the mean time :smile:

It does work, but there are two disadvantages:

  • To maintain accuracy a lot of sections are required, which result in a lot of clicking
  • I would like to create a fillet that is 150 exact, so a filletSrf in one direction is required (or I have to fillet every section crv…)

Any idea’s?

create frames2.3dm (2.6 MB)

Hi Thomas- for the multiple sections, assuming they are all in parallel planes, use Contour instead of Section.

-Pascal

Yes, I did that. Sections would be a lot of work.

But, after Contouring, every curve needs attention.
Every curve must be selected to offset in the correct direction and than every curve must be selected to create a loft.
(I understand that you can select more curves for the loft at once, but still.)

What I am looking for is a kind of offset/sweep/thicken, where the following process is automated:

User input:
-Select srf
-Choose offset side
-Choose distance
-Choose vector (eg. Y-axis)

Process:
-Contour the input Surface with a standard tolerance
-Offset every curve in the vector direction
-Create a loft with all offset crv’s
-Create a solid (optional)

-thomas

edit: I am not looking for a script, this command is very common in other 3d software

Are you sure? a script is likely the best that can be done in the short or even medium term…

-Pascal

A script should do the job, but I think this should be implemented in rhino.

This is what I made, quite usefull in my opinion!

-_RunPythonScript (
import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc

“”“Offset surface in YZ plane, uses active CPlane
Script by Thomas Brandwijk 07.03.2016"”"

def OffsetSrfYZ():

question1=rs.MessageBox("Info before you start:  Untrim and split your surface first to create a proper Help Geometry surface.", 1 | 32, title="Offset Surface in YZ plane")

if question1 == 1:
    obj = rs.GetObject("Select surface to offset in YZ plane", rs.filter.surface + rs.filter.polysurface,preselect=True)
    
    dist=rs.GetReal("Enter offset distance...")
    if not dist: return
    
    point=rs.GetPoint("Pick offset side..")
    if not point: return
    
    rs.EnableRedraw(False)
    startpoint = [0,0,0]
    endpoint = [1,0,0]
    contours=rs.AddSrfContourCrvs( obj, (startpoint, endpoint) )
    
    for contour in contours:
        contour_new=rs.FitCurve(contour,degree=3,distance_tolerance=0.01,angle_tolerance=1)
        offset=rs.OffsetCurve(contour_new,point,dist,style=0)
        rs.DeleteObject(contour_new)
        rs.SelectObject(offset)
    
    offsets=rs.SelectedObjects()
    rs.AddLoftSrf(offsets,loft_type=0)
    rs.DeleteObjects(offsets)
    rs.DeleteObjects(contours)
    rs.EnableRedraw(True)
if question1 == 2: return

OffsetSrfYZ()
)

Hi Thomas - in case it helps, I monkeyed a little with your script idea-

`import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs

def OffsetSrfYZ():

question1=rs.MessageBox("Info before you start:  Untrim and split your surface first to create a proper Help Geometry surface.", 1 | 32, title="Offset Surface in YZ plane")

if question1 == 1:
    obj = rs.GetObject("Select surface to offset in YZ plane", rs.filter.surface + rs.filter.polysurface, preselect=True)
    if not obj:return
    
    oldOffset = 10
    if sc.sticky.has_key("OLDOFFSET"):
        oldOffset = sc.sticky["OLDOFFSET"]
    dist=rs.GetReal("Enter offset distance", oldOffset)
    if not dist: return
    
    sc.sticky["OLDOFFSET"] = dist

    point=rs.GetPoint("Pick offset side..")
    if not point: return
    
    aBB = rs.BoundingBox(obj)
    p1 = aBB[0]
    p2 = aBB[1]
    
    cutPlane  = Rhino.Geometry.Plane.WorldYZ
    cutPlane.Origin = aBB[1]
    rs.EnableRedraw(False)
    contours=rs.AddSrfContourCrvs(obj, [p1,p2])
    contours.append(rs.AddSrfContourCrvs(obj, cutPlane))
    if len(contours) == 0: return
    if len(contours) == 1:
        rs.DeleteObjects(contours)
        rs.EnableRedraw(True)
        return
        
    crvs=[]
    
    for contour in contours:
        offset=rs.OffsetCurve(contour, point, dist, Rhino.Geometry.Plane.WorldZX.ZAxis, style=0)
        if offset is not None:
            crvs.append(rs.CopyObject(offset[0]))
            rs.DeleteObjects(offset)
    rs.DeleteObjects(contours)
    
    if len(crvs) > 0: 
        rs.AddLoftSrf(crvs,loft_type=0, simplify_method=2)
        rs.DeleteObjects(crvs)
        
        
    rs.EnableRedraw(True)
if question1 == 2: return

OffsetSrfYZ()`

-Pascal

Thanks Pascal! My scripting is very poor :slight_smile:
The changes I recall:

  • Sticky offset real

  • I see you added the plane in which the contours are made

  • Points from bb instead of real numbers

  • I can tell that your script is way more stable, but I have to dive into the python tutorials to reporduce the same…

Thanks for monkeying!

Hmm I get recall why, but it´s not working:

Message: Parameter must be a Guid or string representing a Guid

Traceback:
line 42, in OffsetSrfYZ, "R:\cad\rhino\Plugins\OffsetSrfYZ-v2.py"
line 54, in , “R:\cad\rhino\Plugins\OffsetSrfYZ-v2.py

Line 42= offset=rs.OffsetCurve(contour, point, dist, Rhino.Geometry.Plane.WorldZX.ZAxis, style=0)
if offset is not None:

Hi Thomas - post the surface you are testing and the offset - I just invented a case for my tests, and it might not be realistic.

-Pascal

Actually I added the plane for just the one last contour - the automatic interval was leaving a gap at one end, so the new surface was a little short - I added the plane on the far side of the bounding box to make sure the last contour is generated. There will be cases where that is messy - if the final automatic contour is on or close to that plane.

-Pascal