Select by Block Description


#1

I am totally new to scripting in Rhino and i am trying to find a way to to deal with a specific problem. I am currently using Rhino 5 and I have a file with hundreds of different Blocks in it. I am trying to find a way to be able to select by the contents of the block description. Is this possible?


(Steve Baer) #2

Have you tried the SelBlockInstanceNamed command? That sounds like what you need without having to do any scripting.


#3

Thank you for your reply. Yes I have tried that but unfortunately I can only select by block name and not by block description. Basically the blocks are named with a number (ex 00230) and in their description they have a text that describes them (material, person who made them, date of construction, date modified, date photographed etc…). I would like to search based on the content of this description and select for example all objects that constructed in 2008. I am not sure if i am making myself clear.


(Dale Fugier) #4

It is possible to write a script, using either RhinoScript or RhinoPython, to select block instances by their block description.

Here is an example of such a script using RhinoScript:

https://gist.github.com/dalefugier/5950022

For more information on RhinoScript, see the following link:

http://wiki.mcneel.com/developer/rhinoscript

– Dale


(Steve Baer) #5

Here’s the exact same script written in python

import rhinoscriptsyntax as rs

def TestSelectBlockByDescription():
    instances = rs.ObjectsByType(rs.filter.instance)
    if not instances:
        print "No block instances found."
        return
    description = rs.GetString("Block description")
    if not description: return
    rs.EnableRedraw(False)
    for instance in instances:
        name = rs.BlockInstanceName(instance)
        instdesc = rs.BlockDescription(name)
        if instdesc and instdesc.lower()==description.lower():
            rs.SelectObject(instance)
    rs.EnableRedraw(True)

if __name__=="__main__":
    TestSelectBlockByDescription()

(Brian Gillespie) #6

Neither of these solve the problem the OP asked: to search in a block description and select based on that search. Your code only does full matches of the description.


(Steve Baer) #7

Fancy text searching ala google is pretty tough and I would recommend looking into using a python or .NET library to perform the perform this if it is even needed for your problem.

If you are just looking for simple keyword matches in the description, then you could check to see if the description contains your unique keyword. The following would select every block that has the word ‘2008’ in the description if you typing 2008 as the input to search for

#change if instdesc and instdesc.lower()==description.lower():
#it
if instdesc and description.lower().find(instdesc)>=0:

(Dale Fugier) #8

For the RhinoScript sample, just replace the call to StrComp with a call to InStr.

http://msdn.microsoft.com/en-us/library/wybb344c(v=vs.84).aspx


#9

Thank you again for you replies. Both the rhinoscript and Python examples work when I have a single word in the description and enter the the exact word to select. Unfortunately in the python version i have tried to change to

if instdesc and description.lower().find(instdesc)>=0:  

but still if there are multiple words I cannot write one of the words and have it selected.

As far as the rhinoscript i tried to replace the StrComp unsuccesfully.


(Steve Baer) #10

Right, that’s why I mentioned that fancy text searching can be pretty difficult. If you want to support multiple words, you could split the text into single word ‘tokens’ by splitting on spaces and then seeing if any of the words are in your description.

Another option is to be very consistent with how you write the descriptions; maybe something like
material: gold
cost: 46
weight: 10

Then you could change your script to search for specific ‘attributes’ in your description.


(Dale Fugier) #11

Here is the RhinoScript version that uses InStr:

Option Explicit

Call TestSelectBlockByDescription()

Sub TestSelectBlockByDescription()
	
	Dim arrInstances, strInstance
	Dim strDescription, strName, strInstDesc
	
	arrInstances = Rhino.ObjectsByType(&h1000)
	If IsNull(arrInstances) Then
		Call Rhino.Print("No block instances found.")
		Exit Sub
	End If
	
	strDescription = Rhino.GetString("Block description")
	If IsNull(strDescription) Then Exit Sub
	
	Call Rhino.EnableRedraw(False)
	
	For Each strInstance In arrInstances
		strName = Rhino.BlockInstanceName(strInstance)
		strInstDesc = Rhino.BlockDescription(strName)
		If Not IsNull(strInstDesc) Then
			If (InStr(1, strInstDesc, strDescription, 1) > 0) Then
				Call Rhino.SelectObject(strInstance)
			End If
		End If
	Next
	
	Call Rhino.EnableRedraw(True)

End Sub

#12

Thank you both again. I am totally new to this so most of the scripts look more like chinese to me. I have tried the last rhinoscript and I am running into errors. As far as stevebaer’s reply, this kind of organizing of information is more or less need in the project that I am working on so I will be organizing the information in this way in the future (by attributes). Would it be possible in the specific description example that you posted to search as

*old

or

go*

in the material attribute and still have this block selected?


(Steve Baer) #13

Sure, it all just depends on how you want your search algorithm to work. In it’s simplest form you are just looking for the existence of a chunk of text inside a larger piece of text. I was just demonstrating simple “substring” find type approach. A more powerful approach would be to use regular expressions, but I would hold off of that until you have a decent understanding of the basic script first.