Script for text=layer identification

This is an unashamed request for a bit of scripting to make my life easier :blush:
What I would like to do is to be able to pick an object, preferably a number of objects, and get the layer name as a text block, positioned in the middle of the object (or thereabouts). The text should all be on a separate layer, with a predefined name (or if need be on the current layer). The text properties such as font and size can be the current text settings, no need to request those as part of the script.
I have dabbled with Python scripts in the past, but I am a long way off creating something like this on my own (besides refreshing the bit I did study at the time), so I would be grateful for any help I can get.

Max.

Not very professional, but since I was trying to do some Rhino-Python anyway, this gave me an objective. try this, it only does one object for now.

I always have Rhino-Python page open in a tab for reference.

#create TextObject from Object's layer, Randy Gregory 2015 

import rhinoscriptsyntax as rs


#text height
tHt=0.75

#Make layer for TextObject
rs.AddLayer("Layer ID Text", (255,38,0))

#Object to get for layer ID
originalObject=rs.GetObject("Select Objects for Layer ID", filter=16, preselect=False, select=True)

if originalObject:
    Layer=rs.ObjectLayer(originalObject)

#create point for textObject placement
point = rs.GetPoint("Point for text insertion")
if point:
    tObjs=[]

#create your text string
textString=Layer

TextObject = rs.AddText(textString,point,tHt)

#change layer of text string
rs.ObjectLayer(TextObject, "Layer ID Text")

IHTH Ā«Randy

Thanks Randy. I had to add the standard line :ā€œimport rhinoscriptsyntax as rsā€, but after that it works just fine. A question though (for my Python-re-education): what does
if point:
tObjs=[]
do?

Max.

It is creating the point object from GetPoint so AddText has physical point for insertion placement. AddText needs a point or plane, see syntax below.

I am still a beginner at using Python and sometimes I see code that works and donā€™t really know why :confused:

AddText - Adds a text string to the document.
Syntax
rhinoscriptsyntax.AddText ( text, point_or_plane, height=1.0, font=ā€œArialā€, font_style=0, justification=None )

This might be useful if you need to place layer name at object centre .

origin = rs.SurfaceVolumeCentroid(originalObject)
objectCentroid = rs.AddPoint(origin[0])

Was working on a script to scale from centre yesterday.

Tot zeins

Thanks again, Randy. I think you have rekindled my interest in Python scripting, I looked up the script that I made before (investigating duplicate line objects), and I immediately saw some things I would like to use in your script, like creating a new layer if one does not exist yet, and making it the current layer from the start. I will struggle forward, thanks for your kick-off.

Tot ziens,

Max.

(now, how can I make it repetitiveā€¦)

1 Like

So Iā€™m a Python greenhorn, too, and Iā€™m not following the tObjs=[] thing either. Mostly because I donā€™t see where you ever use tObjs after you create it.

FYI, it seems that GetPoint is sufficient, the AddText will use the acquired coordinates without creating tObs first. I hatched out the lines for now, works OK.

Max.

Yes, i had a multiline string in my file I pulled that from and it was used for that reason. So I was adding multiple inputs into one text string to place as textObject.

Just delete ā€¦

if point:
    tObjs=[]

it is not necessary.

Ha! Iā€™ve got it:

Multiple layer name labels.py (720 Bytes)

The difficult part was to realize that GetObjects results in a tuplet of Guids, but you have to convert them in a list to scan through them to get to the properties of each Guid.

Max.

(how do you show the .py file, rather than just a link?)

Copy code, paste into this window. Then select it here and then click the icon to the left of the Upload icon.

Cool ā€¦ Ā«Randy

Just trying here on a few closed polysurfaces and it does not work. If I explode and select surfaces it works great. just for you to know. I thought it nay have been the rs.SurfaceVolumeCentroid

Like so :smile: :

#Create Layer Name Text Object for Surfaces,  Max Zuijdendorp, March 2015

import rhinoscriptsyntax as rs

# Check if a layer "Layer Names" exists, if not, add it.
if not rs.IsLayer("Layer Names"):
    rs.AddLayer("Layer Names", (0,0,0))

# Make "Layer Names" the current layer
rs.CurrentLayer("Layer Names")

# Pick a set of surfaces to be identified with the layer name
SelectIds = rs.GetObjects("Select Surfaces to label", filter=8, preselect=True, select=False)

List=[]
for i in range(0,len(SelectIds)):
	
	Laag=rs.ObjectLayer(SelectIds[i])
	
	origin = rs.SurfaceAreaCentroid(SelectIds[i])
	point = rs.AddPoint(origin[0])

#create your text object
	rs.AddText(Laag,point,height=8,font="Arial",font_style=0,justification=2)

Thx,
Max.

Edit: I compacted the script a bit, works a treat :smiley:

It was the SurfaceVolumeCentroid, changed it to SurfaceAreaCentroid. I need it mostly for surfaces anyway.

1 Like

It turns out this is not true. I donā€™t remember how I came to this conclusion, but I deleted ā€œListā€, and it works just fine.

Max.

I might use the objectā€™s bounding box center for the labelā€¦ This will work with non-surface objects like curves as well.

ā€“Mitch

import rhinoscriptsyntax as rs

def TextLabelBBCtr():
    objs=rs.GetObjects("Select objects to label", 4+8+16+32, preselect=True)
    if not objs: return
    
    label_layer="Text_Labels"
    #if layer doesn't already exist, add it.
    if not rs.IsLayer(label_layer): rs.AddLayer(label_layer)
    
    """text plane is either active view's CPlane or text plane is always World XY
    comment/uncomment one or the other of the next two lines"""
    
    #text_plane=rs.ViewCPlane()
    text_plane=rs.WorldXYPlane()
    
    #text height is constant
    text_ht=1.0
    
    for obj in objs:
        bb=rs.BoundingBox(obj)
        #move text plane origin to bounding box center point
        text_plane.Origin=(bb[0]+bb[6])/2
        #get object's layer name
        obj_layer=rs.ObjectLayer(obj)
        #add the text
        rs.AddText(obj_layer,text_plane,text_ht, justification=2+131072)
TextLabelBBCtr()

Thanks, well done. A definition question, if you do not mind?

I had some help with a script the other day, and I asked about using definitions for scripts, the answer I got was that it can be reused in the script, but can a definition be called from another python script in the same folder?

for obj in objs - works the code after on each object, saw this before and now I get it more clearly.

Thanks again,
Ā«Randy

Found some info on functions / definitions (defining functions), I think I am getting it.

Python Functions

It is possible, but I donā€™t recommend itā€¦ It makes your script less portable should you give it out to someone, or change the directory where the imported module is locatedā€¦ Unless itā€™s something really, really complex, I prefer to keep the function definitions inside the main script file, that way the script is self-contained.

My simple way to explain the use of function definitions on a basic level is that they work just like the normal rhinoscriptsyntax methods - except that you write the method yourself. The function definition will execute an operation or series of operations when you call it inside your main script. You can have as many input arguments as you want (or none, theyā€™re optional); the function can return something or not, also optional.

The advantage of encapsulating operations sequences inside function definitions is that it can make your code more readable/understandable, and the definitions can be re-used as many times as you need using only one line of code in the main script body.

Edit:
Also, you will see that even the main body of the script is encapsulated in a function definition. This is done for one primary reason, to be able to ā€œescapeā€ the script gracefully with ā€œreturnā€ if something goes wrong or the user decides to abort it for some reasonā€¦

ā€“Mitch

1 Like

Thanks for your alternative script, Mitch. I was just about to create a second script for polysurfaces, this time using leaders i.s.o. text blocks. I had found the BoundingBox syntax, but you showed me a simpler way of referring to a midway point than I had in mind ( intersecting curves and all).
Also, I learned from it how to simplify stepping through a multi object variable. Thanks.

Max.

I see this going through the Python tutorial on the link I posted before.

Thanks for the explaination.