Site Tools


Auto Label Objects with Script

Developer: RhinoScript and RhinoPython
Summary: Demonstrates how to automatically label objects using a script.

Overview

The following example demonstrates how to automatically add a label, or text dot, to selected objects. A label number is automatically generated based on the geometric positions of the objects. In this example, Curve, Surfaces and Point objects are labeled. But, the code could easily be modified to support other object types. The Objects Names are also modified with the label.

RhinoScript

Option Explicit
 
'
' AutoLabel Subroutine
'
Sub AutoLabel
   ' Declare variables
   Dim arrDirPoint1, arrDirPoint2, arrSortDir, arrObjects, arrPoint, arrItem, arrArea, arrPrompts, arrCollect()
   Dim strObject, strName, strDot
   Dim intCount, intSuffix, intXDir, intYDir, intZDir
   Dim i, j, temp
 
   ' Select objects      
   arrObjects = Rhino.GetObjects("Select objects to name")
   If Not IsArray(arrObjects) Then Exit Sub
 
   ' Prompt for a prefix to add to the labels
   strName = Rhino.GetString("Prefix for labels, press Enter for none")
   If Not IsString(strName) Then Exit Sub
 
   ' Prompt for a suffix starting number
   intSuffix = Rhino.GetInteger("Starting base number to increment",0)
   If IsNull(intSuffix) Then Exit Sub
 
   ' Prompt for direction
   arrDirPoint1 = Rhino.GetPoint("Base point for sort direction")
   If IsNull (arrDirPoint1) Then Exit Sub
   arrDirPoint2 = Rhino.GetPoint("Pick point for sort direction", arrDirPoint1)
   If IsNull (arrDirPoint2) Then Exit Sub
 
   ' Determine Direction of sort for each axis, 0 is Negative Direction, 1 is positive
   If arrDirPoint1(0) > arrDirPoint2(0) Then
     intXDir = 0
   Else
     intXDir = 1
   End If
   If arrDirPoint1(1) > arrDirPoint2(1) Then
     intYDir = 0
   Else
     intYDir = 1
   End If
   If arrDirPoint1(2) > arrDirPoint2(2) Then
     intZDir = 0
   Else
     intZDir = 1
   End If
   arrSortDir = Array(intXDir, intYDir, intZDir)
 
  ' Initialize collection counter
   intCount = 0
 
   ' Process each seleted object
   For Each strObject In arrObjects
 
     ' Process curves
     If Rhino.IsCurve(strObject) Then
       ' Get the curve starting point
       arrPoint = Rhino.CurveStartPoint(strObject)
       ' Append the object name to the point array
       ReDim Preserve arrPoint(3)
       arrPoint(3) = strObject
 
       ' Append the modified point array to the collection     
       ReDim Preserve arrCollect(intCount)
       arrCollect(intCount) = arrPoint
 
       ' Increment collection counter
       intCount = intCount + 1
     End If
 
     ' Process surfaces
     If Rhino.IsSurface(strObject) Then
       ' Get the Surface center point
       arrArea = Rhino.SurfaceAreaCentroid (strObject)
       arrPoint = arrArea(0)
       ' Append the object name to the point array
       ReDim Preserve arrPoint(3)
       arrPoint(3) = strObject
 
       ' Append the modified point array to the collection     
       ReDim Preserve arrCollect(intCount)
       arrCollect(intCount) = arrPoint
 
       ' Increment collection counter
       intCount = intCount + 1
     End If
 
     ' Process points
     If Rhino.IsPoint(strObject) Then
       ' Get the Point Corrdinates point
       arrPoint = Rhino.PointCoordinates (strObject)
       ' Append the object name to the point array
       ReDim Preserve arrPoint(3)
       arrPoint(3) = strObject
 
       ' Append the modified point array to the collection     
       ReDim Preserve arrCollect(intCount)
       arrCollect(intCount) = arrPoint
 
       ' Increment collection counter
       intCount = intCount + 1
     End If
 
     '
     ' TODO: add support for additional object types here
     '

   Next
 
   ' Validate the collection
   If Not IsUpperBound(arrCollect) Then Exit Sub
 
  ' Bubble sort the collection
   For i = UBound(arrCollect) - 1 To 0 Step -1
     For j = 0 To i
       If CompareItems(arrCollect(j), arrCollect(j+1), arrSortDir) = True Then
         temp = arrCollect(j+1)
         arrCollect(j+1) = arrCollect(j)
         arrCollect(j) = temp
       End If
     Next
   Next
 
   ' Process each item in the collection
   For i = 0 To UBound(arrCollect)
     ' Get an item from the collection
     arrItem = arrCollect(i)
     ' Rebuild the point array
     arrPoint = Array(arrItem(0), arrItem(1), arrItem(2))
   'Curves need to have the textdot at thier Midpoint
    If Rhino.IsCurve(arrItem(3)) Then
     arrPoint = Rhino.CurveMidPoint(arrItem(3))
    End If
    ' Add a text dot at the point location
    strDot = Rhino.AddTextDot(strName & CStr(intSuffix + i), arrPoint)
    ' Set the dot name to the originating object
    Rhino.ObjectName strDot, arrItem(3)
    Rhino.ObjectName arrItem(3), strName & CStr(intSuffix +i)
    Rhino.SetObjectData arrItem(3), "AutoCount", "DotUiid", strDot
   Next
End Sub
 
'
' Compare function for bubble sort
'
Function CompareItems(x, y, dir)
   If x(0) > y(0) Then
     If dir(0) = 1 Then
       CompareItems = True
     Else
       CompareItems = False
     End If
   ElseIf x(0) = y(0) Then
     If x(1) > y(1) Then
       If dir(1) = 1 Then
         CompareItems = True
       Else
         CompareItems = False
       End If
     ElseIf x(1) = y(1) And x(2) >= y(2) Then
       If dir(2) = 1 Then
        CompareItems = True
       Else
         CompareItems = False
       End If
     Else
       If dir(1) = 1 Then
         CompareItems = False
       Else
         CompareItems = True
       End If
     End If
   Else
     If dir(0) = 1 Then
       CompareItems = False
     Else
       CompareItems = True
     End If
   End If
End Function
 
'
' Returns a Boolean value indicating whether an
' expression can be evaluated as a string
'
Function IsString(ByVal str)
  IsString = False
  If VarType(str) = vbString Then IsString = True
End Function  
 
'
' Returns a Boolean value indicating whether an 
' array has been dimensioned.
'
Function IsUpperBound(ByVal arr)
   IsUpperBound = False
   If IsArray(arr) Then
     On Error Resume Next
     UBound arr
     If Err.Number = 0 Then IsUpperBound = True
   End If
End Function  

Python

import rhinoscriptsyntax as rs
 
# AutoLabel Subroutine
def AutoLabel():
    # Select objects      
    arrObjects = rs.GetObjects("Select objects to name")
    if not arrObjects: return
 
    # Prompt for a prefix to add to the labels
    name = rs.GetString("Prefix for labels, press Enter for none")
    if name is None: name = ""
 
    # Prompt for a suffix starting number
    suffix = rs.GetInteger("Starting base number to increment",0)
    if suffix is None: return
 
    # Prompt for direction
    dirPoint1 = rs.GetPoint("Base point for sort direction")
    if not dirPoint1: return
    dirPoint2 = rs.GetPoint("Pick point for sort direction", dirPoint1)
    if not dirPoint2: return
 
    # Initialize collection
    collection = []
 
    # Process each seleted object
    for obj in arrObjects:
        # Process curves
        if rs.IsCurve(obj):
            # Get the curve starting point
            point = rs.CurveStartPoint(obj)
            collection.append( (point, obj) )
 
        # Process surfaces
        if rs.IsSurface(obj):
            # Get the Surface center point
            point, error = rs.SurfaceAreaCentroid(obj)
            collection.append( (point, obj) )
 
        # Process points
        if rs.IsPoint(obj):
            # Get the Point Corrdinates point
            point = rs.PointCoordinates(obj)
            collection.append( (point, obj) )
 
        # TODO: add support for additional object types here
 
    # Determine Direction of sort for each axis
    sortDir = dirPoint2 - dirPoint1
    # compare function for sorting
    def sortcompare(a, b):
        pointa, pointb = a[0], b[0]
        rc = cmp(pointa.X, pointb.X)
        if sortDir.X<0: rc = -1*rc
        if rc==0:
            rc = cmp(pointa.Y, pointb.Y)
            if sortDir.Y<0: rc = -1*rc
        if rc==0:
            rc = cmp(pointa.Z, pointb.Z)
            if sortDir.Z<0: rc = -1*rc
        return rc
    # sort the collection
    collection = sorted(collection, sortcompare)
 
    # Process each item in the collection
    for point, item in collection:
        #Curves need to have the textdot at thier Midpoint
        if rs.IsCurve(item): point = rs.CurveMidPoint(item)
        # Add a text dot at the point location
        dot = rs.AddTextDot(name + str(suffix), point)
        # Set the dot name to the originating object
        rs.ObjectName(dot, item)
        rs.ObjectName(item, name+str(suffix))
        rs.SetUserText(item, "AutoCount::DotUuid", dot)
        suffix += 1
 
if __name__=="__main__":
    AutoLabel()



developer/scriptsamples/autolabel.txt ยท Last modified: 2015/09/14 (external edit)