Python – move a mesh using pythonscript


#1

I want to move a mesh cube from its volume-centroid to the point 0,0,0 … but I need it to be done fully automated by the python script without picking any thing from the screen …

I am a beginner … so please help me as long as you can .

  • I tried this code , but turns Error :-

import rhinoscriptsyntax as rs

def myFunction(object,translation):
rs.MoveObject(object,translation)

hossam = rs.ObjectName(32)

start = rs.MeshVolumeCentroid(hossam)
End = rs.GetObject(0,0,0)
translation = end-start

myFunction(hossam,translation)

thanks in advance !


#2

Hi Hossam,

You want to move your cube mesh from its centroid point to 0,0,0 point?
If that is so, try this:

import rhinoscriptsyntax as rs

def moveMesh():
    reqName = rs.GetString("Object of what name do you want to move")
    rs.Command("-_SelAll")
    objects = rs.GetObjects(preselect=True)
    if objects:
        for obj in objects:
            name = rs.ObjectName(obj)
            if name == reqName:
                if rs.IsMesh(obj):
                    centroid = rs.MeshVolumeCentroid(obj)
                    if centroid:
                        vector = rs.VectorCreate ([0,0,0], centroid)
                        rs.MoveObject(obj, vector)
                        print "Done"
                        break
                    else:
                        print "Something is wrong with your mesh. Function terminated"
                        return
                else:
                    print "You have not picked a mesh. Function terminated"
                    return
            else:
                if obj == objects[-1]:
                    print "Object of that name does not exist. Function terminated"
                    return
                continue
    else:
        print "Your file is empty. There's nothing to select"
        return

moveMesh()

EDIT: I added a bit of additional debugging.
Also when posting your code, you need to enclose it with python on the beginning, and at the end. This will format and highlight your code.
moveMesh.py (1.2 KB)


#3

Thanks Dear djordje ,

but still it needs " picking " the mesh manually to achieve the operation ! … would it be any way to auto-select the mesh ?! … in macros I used to type :-

_selmesh (( as it is the only mesh in the file ))
_setobjectname name
_selnone
_selobjectname name
_meshvolumecentroid (( I know that there is no need to name the mesh in order to select it , as it is the only mesh , but I want to name it for a different reason ))

is there is any similar way in python script ?! … I have large number of files that I need to import and translate then export again one by one … and I need to achieve it (( edit them all by one python .txt file )) so that it will reduce time .

and many thanks to you


#4

If you are SURE there is only one mesh in the file, then you can use

meshObjs=rs.ObjectsByType(32)
if meshObjs : meshObjID=meshObjs[0]

–Mitch


#5

You are right.
Sorry about missing that part.
Check the edited solution in the upper reply, now.

By the way:
I am trying to show you how to enclose your code, but I could not do that, as discourse automatically converts tags into code block. Just read this topic, and it would be more clear to you.


#6

Dear djordje,

I used your code and it didn’t work ! … ignore naming the mesh … I don’t need to name it now …

would you please type the whole code to move the mesh automatically as there is no mesh except 1 mesh in the whole file ?! … so that this code would apply on any file contained only one mesh in it ?!

sorry I just begin reading in python from 2 days !

and for enclosing the code … I read the thread and it was very useful … thanks alot :slight_smile:

thanks alot !


#7

Thanks alot Dear Helvetosaur ! … but I don’t know how to replace it in the code ! … sorry I am a beginner


#8

In your original post you used the ObjectName() function.
So I thought that was the criterion for picking up a mesh (its name).

Here is an edited version which only picks the first mesh it finds in the .3dm file.

moveMesh2.py (958 Bytes)


#9

Many thanks Dear djordje ! … it actually works … :smiley:

I have another question please … sometimes meshes are used to be opened … have some holes … does python has any thing to do with this or I got to repair it manually ?! … that make problems for me as I couldn’t obtain volume centroid from an open mesh !


#10

You have two types of centroids: area and volume ones. I think (maybe I am wrong) these two could be distinguished by using the rs.IsMeshClosed() function.

I added the following condition and attached the changed file:

if rs.IsMeshClosed(obj):
    centroid = rs.MeshVolumeCentroid(obj)
else:
    centroid = rs.MeshAreaCentroid(obj)

moveMesh3.py (1.1 KB)

But what is bugging me is: for which specific mesh cases should Volume or Area Centroids be used?
An example: a mesh cube with 5 sides (one is missing). Rhino considers it an opened mesh (IsMeshClosed() returns False).
But does that mean that we need to apply an Area Centroid?
Here is the preview of both Volume and Area Centroids on the same mesh:

This sounds like an advanced question, you might need to consult more experienced users than myself (@Mitch).


#11

Really thanks for your Effort …

In Macros script I found that Rhino always gives a message if the mesh is open , this message tells me that volume centroid of a mesh is meaningless as it is opened " , it gives me the option to continue any way or not …

but in python script no message appeared , either open or closed mesh … rhino dealt in the same way … and it completes the mission successfully without any message …

I used to check the similarity of the mesh volume centroid data before repairing it (( opened mesh )) & after repairing it (( closed mesh )) , finally I found that there is no difference at all ! … so I guess there is no need to bother ourselves repairing every mesh to obtain its volume centroid … neither think about the volume centroid of an open cube , cause it will be the same as closed one ! …

Area centroid is for 2D meshes … it applies only for x,y … volume centroid is dealing with 3D (( axis )) x,y,z … it’s totally different and if you use area centroid to obtain volume centroid of an open mesh you will not obtain accurate result as shown in your picture … cause it’s totally different aspect !

*** (( out of context ))

I used to write this code to “automatically” import my file from a definite path using python script in order to translate the mesh object then export it to a definite path … but it’s not working … it always ask me to determine the file manually ! … what is the right code to automate this ?!

    import rhinoscriptsyntax as rs
rs.Command("_import D:\library\USB\Genesis\prima 4.1.STL") 

def moveMesh():
    rs.Command("-_SelAll")
    objects = rs.GetObjects(preselect=True)
    if objects:
        for obj in objects:
                if rs.IsMesh(obj):
                    centroid = rs.MeshVolumeCentroid(obj)
                    if centroid:
                        vector = rs.VectorCreate ([0,0,0], centroid)
                        rs.MoveObject(obj, vector)
                        print "Done"
                        break
                    else:
                        print "Something is wrong with your mesh. Function terminated"
                        return
                else:
                    if obj == objects[-1]:
                        print "You do not have a mesh in your file. Function terminated"
                        return
                    continue
    else:
        print "Your file is empty. There's nothing to select"
        return

moveMesh()

#12

Here is the final version: moveMesh4.py (1.8 KB)

I can see you have been looking for an export feature too.
The attached function prompts you to pick your .stl file, then takes a planar or solid mesh, moves it to the coordinate center point, and exports the .stl file with the same name as the imported one (overwrites it).

For any future topics: please define clearly on the very beginning what you would like your script to do.
Thank you.


#13

Thanks Dear … I will try to be clearer next time …

I checked your file … where could I paste my file path ?! … I need it to be imported from a location then exported to other location … where could I place my file address inside the code ?! … I don’t want to pick it manually … I want to import it automatically from the code then edit it & export it ( rewrite it ) then delete it , then import another file with different address the edit it then export ( rewrite ) it … and so on ! …

I want to make all these operation automatically from the file without pick any single think from the screen or pick any address !

Thanks alot for your help …


#14

Isn’t using a Windows file open dialog box to pick up the file, a higher level of automatisation, then manually searching for the line in code, and then changing that line into specific file path?

Nevertheless here is the version with manual ability to change the file path:
meshMove5.py (1.8 KB)

You need to edit the line 18.

Pay attention to the double backslash characters in the existing file path. You need to do it like that, because in python backslash character is used for escaping characters.


#15

Thanks very much Dear djordje ,

You were very helpful ! … thank you again :smile:


#16

Hi djordje,

I am new to programming and have a question regarding this line:

commandline = "-_import %s ModelUnits=%s _Enter" % (filepath, units)

what does the %s do? And what is the benefit of doing it this way?

Thanks


#17

This is string formatting in Python. The %s is the “classic” way, there is also the new .format method.

Briefly, the %s is a substitution and what is substituted is the first item in the parentheses (filename); the second %s will substitute for the second item. The advantage is the things being substituted in automatically get converted into strings and there are some formatting possibilities for doing so. It’s pretty powerful, but also somewhat complicated.

.format example:

print "I would like {} green {} and {} slices of spam".format(3,"eggs",1/2)

num=1.039585
print "Rounded to 3 digits, "+str(num)+" will become {:.3f}".format(num)

http://docs.python.org/2/library/string.html

–Mitch


#18

Ok, thanks… I can see that this makes it easy to arrange if one is used to programming.


#19

Dear Helvetosaur

I tried this code to automatically import files from pathes and edit it then export it again to replace the original file … but it turns “Your file is empty. There’s nothing to select” … is that because white spaces in the file name ?! … what I can I do for this ?!

import rhinoscriptsyntax as rs


def moveMesh(filepath):
    unitI = rs.UnitSystem()
    if unitI == 2:
        units = "Milimeters"
    elif unitI == 3:
        units = "Centimeters"
    elif unitI == 4:
        units = "Meters"
    elif unitI == 8:
        units = "Inches"
    elif unitI == 9:
        units = "Feet"
    else:
        return

    #filepath = "C:\\Users\\Hossam\\Desktop\\CT\\IFNT410_mm.stl"
    commandline = "-_import %s ModelUnits=%s _Enter" % (filepath, units)
    rs.Command(commandline)
    rs.Command("-_SelAll")
    objects = rs.GetObjects(preselect=True)
    if objects:
        for obj in objects:
                if rs.IsMesh(obj):
                    volume = rs.MeshVolume(obj)
                    if volume[1] > 0:
                        centroid = rs.MeshVolumeCentroid(obj)
                    else:
                        centroid = rs.MeshAreaCentroid(obj)
                    if centroid:
                        vector = rs.VectorCreate ([0,0,0], centroid)
                        rs.MoveObject(obj, vector)
                        rs.RotateObject(obj,(0,0,0),90)
                        rs.Command("_SelAll")
                        commandline = "-_export %s  _Enter _Enter" % filepath
                        rs.Command(commandline)
                        print "Done"
                        break
                    else:
                        print "Something is wrong with your mesh. Function terminated"
                        return
                else:
                    if obj == objects[-1]:
                        print "You do not have a mesh in your file. Function terminated"
                        return
                    continue
    else:
        print "Your file is empty. There's nothing to select"
        return

pathes = ["c:\\Users\\Hossam\\Desktop\\CT\\3.8 x 10 Straight.stl",
"c:\\Users\\Hossam\\Desktop\\CT\\3.8 x 10 Tapered.stl",
"c:\\Users\\Hossam\\Desktop\\CT\\3.8 x 11.5 Straight.stl",
"c:\\Users\\Hossam\\Desktop\\CT\\3.8 x 11.5 Tapered.stl",
"c:\\Users\\Hossam\\Desktop\\CT\\3.8 x 13 Straight.stl",
"c:\\Users\\Hossam\\Desktop\\CT\\3.8 x 13 Tapered.stl",
"c:\\Users\\Hossam\\Desktop\\CT\\3.8 x 16 Straight.stl"]

for x in range (0, len(pathes)):
    moveMesh(pathes[x])
    rs.Command("-_selall")
    rs.Command("-_delete")

#20

Millimeters is spelled wrong (two "L"s), don’t know if that makes a difference…

–Mitch