Rectangle border around text

Hi!

Is there a way te create rectangle borders around multipe text’s?

BoundingBox will do that, but it will create a box that is tight around the text. For small numbers of objects, you can then offset the rectangle(s). For an automatic function on larger numbers of texts, I think a script will be necessary.

–Mitch

Thanks!

If all text is selected, only one big BoundingBox is created.

So indeed a script is necessary, I am not very good at scripting… this is wat I got so far:

Option Explicit

Call TextBorder()
Sub TextBorder()

Dim aObj, sObj, i, BBox

Rhino.ClearCommandHistory


aObj = Rhino.GetObjects("Select Text..", , True)
If Not isarray(aObj) Then Exit Sub

BBox = Rhino.BoundingBox(aObj(i))


If IsArray(aObj) Then
	Rhino.EnableRedraw False

	For Each sObj In aObj
	
		rhino.BoundingBox sObj
		
					
	Next
	

	Rhino.ClearCommandHistory
	

	Rhino.EnableRedraw True
	
	
	
End If

End Sub

Doesnt work jet, any suggestions?

Hi Thomas
the below script in Pyhon is ok
the equivalent in vbscript is buggy

import rhinoscriptsyntax as rs
def rt():
    
    testi=rs.GetObjects("seleziona testi")
    for testo in testi:
        rs.SelectObject(testo)
        rs.Command("_BoundingBox enter")
        rs.UnselectAllObjects()
    
    
rt()

Ciao Vittorio

I prefer to write this in Python, it just works nicer… Creates an offset rectangle around text objects in any plane, offset is user-settable and sticky within session.

"""Creates an offset rectangle around each selected text object
Text can be in any plane, rectangle is created in same plane as text object.
Script by Mitch Heynick 19 December 2014"""

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

def text_filt(rhino_object, geometry, component_index):
    return rs.IsText(geometry)

def TextOffsetBoundingBox():
    msg="Select texts for bounding box"
    objs=rs.GetObjects(msg,512,preselect=True, custom_filter=text_filt)
    if not objs: return
    
    if "TO_BB_PrevValue" in sc.sticky: prev_offset = sc.sticky["TO_BB_PrevValue"]
    else: prev_offset = 1.0
    
    offset=rs.GetReal("Offset value?",prev_offset,0)
    if offset==None: return
    
    for objID in objs:
        plane=rs.TextObjectPlane(objID)
        xform=rs.XformRotation1(plane,rs.WorldXYPlane())        
        obj=sc.doc.Objects.Find(objID).Geometry
        obj.Transform(xform)
        bb=obj.GetBoundingBox(plane)
        bb.Inflate(offset)
        pts=bb.GetCorners()
        cp=rs.PointArrayTransform(pts,rs.XformPlanarProjection(rs.WorldXYPlane()))
        xform=rs.XformRotation1(rs.WorldXYPlane(),plane)
        cp=rs.PointArrayTransform(cp,xform)
        rect=Rhino.Geometry.Polyline([cp[0],cp[1],cp[2],cp[3],cp[0]])
        sc.doc.Objects.AddPolyline(rect)
    sc.doc.Views.Redraw()
    sc.sticky["TO_BB_PrevValue"] = offset
TextOffsetBoundingBox()

–Mitch

Edit: odd, I see the formatting in the preview box, but it disappears when I submit.

TextOffsetBoundingBox.py (1.4 KB)

Super thanks!!

Works perfect!!

I am going to learn some scripting…

what also be super usefull for us, is to create blocks of each text and border. Is that an easy addition to this script? The block name can be the same as the text or just a specific text.

Thanks in advance!

Should be possible… Since you can have the same text multiple times, the block name couldn’t necessarily be the text - as block names need to be unique. You could just let Rhino add the block name as it sees fit (Block 01, Block 02, etc.) or there would have to be a mechanism for checking and creating unique block names. Where would you want the insertion point? The text object point, or world 0 or…?

–Mitch

Cool!

Little explanation of the end goal:
The purpose of this script is to add a posnr (object identification) derived from an attribute and place it to the middel of the bbbox of an object.
The posnr itself should have a offset border and combined to a block.
The name of the block should be the same name as the text (posnr).
The basepoint is the middle of the block (border).

The script below is a script to derive the attribute info from an object.
Is this can be combined in one script is would be awesome!!

Option Explicit
'Script written by David Rutten
Sub AutoAnnotateNamedObjects()
	Dim selObjects, i
	Dim midPoint, strName, strFont
	
	strFont = "ISOCPEUR"
	selObjects = Rhino.GetObjects("Select objects to annotate...", 4 + 8 + 16, vbFalse, vbTrue, vbTrue)
	If IsNull(selObjects) Then Exit Sub
	
	Rhino.EnableRedraw vbFalse
	For i = 0 To Ubound(selObjects)
		strName = Rhino.GetUserText(selObjects(i), "Posnummer")
		If Not IsNull(strName) Then
			midPoint = GetMidPoint(selObjects(i))
			If Not IsNull(midPoint) Then
				Rhino.AddText strName, midPoint, 20, "ISOCPEUR"
			End If
		End If
	Next
	Rhino.EnableRedraw vbTrue
	Rhino.Print "Posnummers added as anotation text objects"
End Sub
AutoAnnotateNamedObjects

Function GetMidPoint(strID)
	GetMidPoint = Null
	Dim BBox, mPoint(2)
	If Rhino.IsCurve(strID) Then
		BBox = Rhino.DivideCurve(strID, 3, vbFalse)
		If IsNull(BBox) Then Exit Function
		mPoint(0) = BBox(1)(0)
		mPoint(1) = BBox(1)(1)
		mPoint(2) = BBox(1)(2)
	Else
		BBox = Rhino.BoundingBox(strID)
		If IsNull(BBox) Then Exit Function
		mPoint(0) = (BBox(0)(0) + BBox(6)(0)) / 2
		mPoint(1) = (BBox(0)(1) + BBox(6)(1)) / 2
		mPoint(2) = (BBox(0)(2) + BBox(6)(2)) / 2
	End If
	GetMidPoint = mPoint
End Function

OK, I guess that’s possible if the posnr is unique, otherwise the script might fail if it tries to make 2 blocks with the same name. Does the object itself need to be included in the block, or just the text and rectangle? Do you have a small sample file with a couple of objects to do some testing?

–Mitch

Ok super!

Just the text and rectangle combined in a block. A sample file is attached. The objects contain attributes (usertext).
Is it also possible to add the objectname as shown in the sample file?

posnr.3dm (286.8 KB)

OK, sorry I haven’t had time to work on it so far… Maybe tomorrow. As concerns your last post and the sample file, my questions are now:

Your object is a 3D object (an extrusion). You would like to extract the usertext of the object plus its name and then place those in a text label for the object at its BB center with the rectangle border.

Since the text does not yet exist, I don’t know what plane to place it in. If the object was a planar curve or surface, I could get its plane, but an arbitrary 3D object does not have a “plane” associated with it. If they are all guaranteed to be extrusions, I could get the extrusion plane, but if they are polysurfaces, there is no real way. I could place it in the current view plane, but again, you would have to make sure that the correct view is active before running the script.

My second comment is simply the BB center placement - for certain geometries, that will not actually be on the object. For example with your inverted “C” shaped top profile S07b, the BB center will be very near its lower edge.

–Mitch

Does using a text mask simplify the rectangle/bounding box part of this?

-Pascal

That was one of the first things I looked at, but I kinda thought the rectangle would be nicer, given that it’s “transparent”… And maybe be able to have the rectangle as “snappable” geometry. These could be added as “wishes” for Text btw…

–Mitch

Mitch!

First of all, thanks for your help and effort so far! I really appreciate this.

Ok, the 3d extrusion object was just a quick export of a bigger model.
We use a custom made plugin and sectiontools to create the production information. This info is divided in 2d production drawings and C-NC output.

The custom made plugin creates C-NC production info, in-place for each part. (see image)

Sectiontools is used to create all 2d section views. So the plane is just top view on the sections.
But sectiontools doesn´t add info to the sections.

You already created a way to add to posnr, so thats awesome. But to check all posnr in acad, we have to perform a block count. Therefore we need the posnr with rectangle to be combined in a block.

The placing is not very important, because we will move and rotate the info in the right position. (unless it’s possible to move and rotate it within the object edges :slight_smile: )

So the step were are missing is the info (posnr and partname) on the 2d sections. If we can select all 2d surfaces and add all info it would be great.

I hoop the above clarifies the process a little bit!

Thanks!!

The 3d construction:

The custom C-NC tool:

The custom C-NC tool:

The 2d sections:

And, Happy birthday Mitch! :smile:

all manual here :frowning:

1 Like

Send me a pm if you want to exchange some method’s specific for the shipbuilding industry.

OK, here is a version to test… It uses the active view’s CPlane to determine which direction the text faces, so make sure the correct view is active before running the script. Should work OK if all objects are aligned parallel to the View CPlane. You have options for rectangle offset and text height (sticky within session).

Let me know if it works for you and what needs adjusting…

Cheers, --Mitch

AddTextBoxNotationView.py (2.3 KB)

Mitch!

That’s a nice Christmas present!!
First day at the office since Christmas, so i’m going to test it right away!

I’ll get back to you.

Regards,
Thomas