Script advice

I have a basic script to scale an object from Centroid.

Looking for advice on better way to write this, as a def maybe. Also I would like to know if it is possible to have option to delete original or not. The VolumeCentroid point can be deleted.

Also if there is a way to convert scaled object to a block.

import rhinoscriptsyntax as rs

obj = rs.GetObject("Select object to scale", filter=16, preselect=False, select=True)
origin = rs.SurfaceVolumeCentroid(obj)

center = rs.AddPoint( origin[0] )

scaleF = rs.GetReal("What is the Scale Factor?", 1.5, 0, 100)
scaleV = [scaleF, scaleF, scaleF]

newObj = rs.ScaleObject( obj, center, scaleV, True )

rs.DeleteObject(center)
rs.DeleteObject(obj)

»Randy

Hi Randy,

I’ve changed a few things. First I did a bit of renaming, for me this always helps when I look at the code later on (readability first). Second I put everything into a function, as you suggested. Third I added two inputs “deleteOriginalObject” and “deleteCentroid”. With these inputs I just created two “if” statements in order to delete/keep these objects.

import rhinoscriptsyntax as rs

def ScaleObjectFromCentroid(deleteOriginalObject=False,deleteCentroid = False):
    originalObject = rs.GetObject("Select object to scale", filter=16, preselect=False, select=True)
    
    origin = rs.SurfaceVolumeCentroid(originalObject)    
    objectCentroid = rs.AddPoint(origin[0])
    
    scaleFactor = rs.GetReal("What is the Scale Factor?", 1.5, 0, 100)
    scaleVector = [scaleFactor, scaleFactor, scaleFactor]
    
    scaledObject = rs.ScaleObject(originalObject, objectCentroid, scaleVector, True )    
    
    if (deleteCentroid):
        rs.DeleteObject(center)
    if (deleteOriginalObject):
        rs.DeleteObject(originalObject)
    return

if(__name__ == "__main__"):
    ScaleObjectFromCentroid(False,False)

I hope this is helpful.

M

Thanks,

So the idea of a Definition is that you can call that

  • From another script (in same folder) ?
  • again in a more complex script ?

So the bracketed items in the first def line have to be the if Statments? And their values, False in this case have to be included at end of definition ?

So these if conditions keep the items highlighted after script has run, giving me the option to delete or keep ?

Thanks for the naming information. Great tip, like keeping layers named properly.

Cheers «Randy

The idea in having them in a function is that you can re-use as many times as you want throughout your code, and if you want to make any changes, you only needed to change it in one place.

def ScaleObjectFromCentroid(deleteOriginalObject=False,deleteCentroid = False):

this means that the parameters are optional, by default the function wont delete the original object and it wont delete the centroid.

if(name == "main"):
ScaleObjectFromCentroid(True,False)

You can change the inputs from true to false, this will give delete or keep the original object and the centroid. This is the function that you can use throughout the code, and by changing the inputs you will get different results with the same piece of code.

1 Like

Something a little more modular.
In the function you should only define what you actually want to do as a functional block of code. Therefore adding the select object method in your function is not a good idea as you would not be able to run the function by passing an object within a script, rather than through selection.

I also prefer using a bounding box centroid for scaling rather than a volume centroid. If you have irregularly shaped or complex objects it works more universally. Just a thought.

import rhinoscriptsyntax as rs
import Rhino

def ScaleObjectFromCentroid( id=None, scaleFactor=1, delOriginal=False, keepCentroid=True):
    bb = rs.BoundingBox(id)
    bbCentroid = Rhino.Geometry.BoundingBox(bb).Center
    vector = Rhino.Geometry.Vector3d(1,1,1)
    scaleVector = vector*scaleFactor

    copy = not delOriginal

    id = rs.ScaleObject(id, bbCentroid, [scaleVector.X, scaleVector.Y, scaleVector.Z], copy)

    if keepCentroid: rs.AddPoint(bbCentroid.X, bbCentroid.Y, bbCentroid.Z)

    return id

def main():

    id = rs.GetObject('Pick object to scale')
    scaleFactor = rs.GetReal('Scale factor')
    delOriginal = rs.GetBoolean('Delete input?', ['Delete', 'No', 'Yes'], ['Yes'])
    keepCentroid = rs.GetBoolean('Add bounding box centroid?', ['BbCentroid', 'No', 'Yes'], ['No'])
    if id: ScaleObjectFromCentroid(id, scaleFactor, delOriginal, keepCentroid)


main()

Thanks @gmacarchitect, once I discovered BoundingBox, I was rewriting one yesterday to do multiple objects at once.

import rhinoscriptsyntax as rs

def ScaleObjectsBBoxCtr():
    objs=rs.GetObjects("Select Objects to Scale", 4+8+16+32+1073741824, preselect=True)
    if not objs: return

    for obj in objs:
        box=rs.BoundingBox(obj)

        center = rs.AddPoint.Origin=(box[0]+box[6])/2

        scaleFactor = rs.GetReal("What is the Scale Factor?", 1.044, 0, 100)
        scaleVector = [scaleFactor, scaleFactor, scaleFactor]

        #Change True to copy original object, False to delete it.
        rs.ScaleObject(obj, center, scaleVector, False )

ScaleObjectsBBoxCtr()

I also like the idea of separating the function from the selection. I will look at tweaking mine after a few more espressos.

A Presto «Randy

1 Like