Rotate text object in a circle

Hi,
I’ve create a list of text objects in a circle, and now I want to ‘orient’ them towards the center of that circle.
As inputs I have:

  • x = text entity list from the ‘Text 3D Advanced’ component.
  • pts = list of center points for the text objects
  • angle = list of angles in degrees between the X axis and the vector between center of circle and each text object

The script is:

import rhinoscriptsyntax as rs

for i in range(0,len(x)):
    pt = pts[i]
    deg = float(angle[i])
    rs.RotateObject(i, pt, deg)

I get the following error:

Runtime error (TypeErrorException): iteration over non-sequence of type int

Traceback:
  line 1795, in TransformObjects, "C:\Users\yafim\AppData\Roaming\McNeel\Rhinoceros\6.0\Plug-ins\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\settings\lib\rhinoscript\object.py"
  line 1498, in RotateObjects, "C:\Users\yafim\AppData\Roaming\McNeel\Rhinoceros\6.0\Plug-ins\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\settings\lib\rhinoscript\object.py"
  line 1466, in RotateObject, "C:\Users\yafim\AppData\Roaming\McNeel\Rhinoceros\6.0\Plug-ins\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\settings\lib\rhinoscript\object.py"
  line 18, in script

Any ideas what I’m doing wrong?
Thanks!

Hi,

rs.RotateObject(i, pt, deg)

The i is an integer.
You need to pass an id there. Probably you have to do something like so first

id = texts[i]
rs.RotateObject(id, pt, deg)

Does that make sense?

Willem

Edit: I answered too quickly. Missing the other info. It’s a little more complex than this. On my phone atm so not able to answer more elaborate.

The following script example seems to work with the quickie test file below… Note that the test file was specifically created to have the order of the objects correspond to each other to make things easier to test - i.e. the points and the texts were created in order from A to F. Note also that in order for the text objects to rotate correctly, in the dimension style edit box, you need to uncheck the “Orient text…” feature.

image

import rhinoscriptsyntax as rs

pt_objs=rs.ObjectsByType(1)
pts=[rs.coerce3dpoint(pt_obj) for pt_obj in pt_objs]
text_objs=rs.ObjectsByType(512)
ctr=rs.coerce3dpoint([0,0,0])
angles=[rs.Angle(ctr,pt)[0] for pt in pts]

for i in range(len(text_objs)):
    rs.RotateObject(text_objs[i], pts[i], angles[i])

RotateTextCircle.3dm (328.7 KB)

Before:
image

After:
image

@Helvetosaur
Thanks for the reply!
I don’t understand some of the lines in your code…

I already have the points as a list so I don’t need this line:

pt_objs=rs.ObjectsByType(1)

I also already set the pts input as a ‘3dpoint’ type so I don’t need to coerce them:

pts=[rs.coerce3dpoint(pt_obj) for pt_obj in pt_objs]

Why do we need this line? I also already have the ‘x’ input to my script as the list of text objects:

text_objs=rs.ObjectsByType(512)

So in the end I only need this, which gives me an error again:

ctr=rs.coerce3dpoint([0,0,0])
angles=[rs.Angle(ctr,pt)[0] for pt in pts]

for i in range(len(x)):
    rs.RotateObject(x[i], pts[i], angles[i])

I’m not sure if I confused you but in general this works for you but not for my case… I think it’s because my inputs are different. What do you think?

Thanks!

Yes, I said that was just an example to show you how it could work. The script is only designed to show the principle and only works on the Rhino file posted with it. It was assumed you could extrapolate from that how to get yours working, as you did not provide any other data or file to work with.

All you need to do is have all your data lists synchronized - the text objects, the rotation angles and the rotation centers - the actual rotate part is trivial.

I dl’d your file and ran the script, it didn’t work so I also tired to take a “geometry” component and select all the letters and points. That didn’t work either.

This is the error I get:

Runtime error (MissingMemberException): 'CustomTable' object has no attribute 'GetObjectList'

Traceback:
  line 1000, in ObjectsByType, "C:\Users\yafim\AppData\Roaming\McNeel\Rhinoceros\6.0\Plug-ins\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\settings\lib\rhinoscript\selection.py"
  line 13, in script

It has to work if you run the above posted script on the downloaded file in Rhino V6 if you have not modified either one. I just re-downloaded to test. It apparently will not work correctly however if you copy>paste to another Rhino instance or save it down to a V5 version - I guess because the order of the objects in the file changes when copied. The whole thing was based on the fact that the order of the points and text is the same so the lists are synchronized.

So, let’s try something completely self-contained. The following will generate synchronized lists of pts, text objects and angles, then rotate the text around the points according to the angles.

import rhinoscriptsyntax as rs
import Rhino

#generate 8 points in a specific order (centered at world 0)
pts=[]
pts.append(Rhino.Geometry.Point3d(50,0,0))
pts.append(Rhino.Geometry.Point3d(50,50,0))
pts.append(Rhino.Geometry.Point3d(0,50,0))
pts.append(Rhino.Geometry.Point3d(-50,50,0))
pts.append(Rhino.Geometry.Point3d(-50,0,0))
pts.append(Rhino.Geometry.Point3d(-50,-50,0))
pts.append(Rhino.Geometry.Point3d(0,-50,0))
pts.append(Rhino.Geometry.Point3d(50,-50,0))

#generate text objects A-H in the same order, centered on pts
text_list=["A","B","C","D","E","F","G","H"]
text_objs=[]
for i in range(len(pts)):
    text_objs.append(rs.AddText(text_list[i],pts[i],10,justification=2+131072))
    
#generate the angles. Note that the rs.Angle function is based on world 0 -
#elsewhere it will not work correctly, you need to calculate the angles differently
ctr=Rhino.Geometry.Point3d(0,0,0)
angles=[rs.Angle(ctr,pt)[0] for pt in pts]

#Now run the rotate part of the script
for i in range(len(text_objs)):
    rs.RotateObject(text_objs[i], pts[i], angles[i])
import rhinoscriptsyntax as rs

pts = []

for i in range(0,len(texts)):
    pts.append(rs.TextObjectPoint(texts[i]))

a = pts

ctr = rs.coerce3dpoint([0,0,0])
angles = [rs.Angle(ctr,pt)[0] for pt in pts]

for i in range(len(texts)):
    #print texts[i]
    #print pts[i]
    #print angles[i]
    rs.RotateObject(texts[i], pts[i], angles[i])

I tried the above code in order to:

  • get only text objects as inputs
  • use ctr 0,0,0 to get angle
  • get points from text objects without using Rhino geometry for those points

The problem with the rotation method is that I can’t get the object_ids of the text objects somehow…
How can I get them?

Thanks

(
btw your previous code ran without errors in Rhino 6 by using:

for i in range(len(pts)):
    sc.doc = Rhino.RhinoDoc.ActiveDoc #required to manipulate the Rhino document
    text_objs.append(rs.AddText(text_list[i],pts[i],10,justification=2+131072))
    sc.doc = ghdoc #bring back editor to manipulate gh

) - but it didn’t actually rotate the letters correctly.

I’m not testing in Grasshopper - it wasn’t tagged either on the post - so the results running a Python script may be different than me running just from the main Rhino script editor… Dealing with getting object IDs of objects that exist in the document into GH, applying transformations to them inside GH and then getting the the transformations back out of GH and applied to the Rhino document objects is beyond me.

1 Like

Updated the topic. Didn’t notice it wasn’t under the right category.
Will wait to see if someone knows solution.
Thanks

Maybe this can give you some idea, its just a quick sketch, but I am not a python guy… sorry about that.

Here is how you would get any text object from rhino doc, rotate it and then bake it again to a layer if you like.

PS: text outlines are just for visualization.


    // will bake in this layer
    var toBake = RhinoDocument.Layers.FindName(layerToBake);
    string layername = RhinoDocument.Layers.CurrentLayer.Name;

    Rhino.DocObjects.RhinoObject[] rhobjs = doc.Objects.FindByLayer(layername);

    List<Curve> curves = new List<Curve>();
    List<Point3d> origins = new List<Point3d>();



    for (int i = 0; i < rhobjs.Length; i++)
    {

      GeometryBase geoBase = rhobjs[i].Geometry;
      BoundingBox b = geoBase .GetBoundingBox(true);
      origins.Add(b.Center);

      Rhino.DocObjects.TextObject textobj = rhobjs[i] as Rhino.DocObjects.TextObject;
      TextEntity textentity = textobj.Geometry as TextEntity;
            
      bool success = textobj.Geometry.Rotate(ToRadians(angles[i]), Vector3d.ZAxis, textentity.Plane.Origin);

      if(success)
      {


        if(bake)
        {
          Rhino.DocObjects.ObjectAttributes att = new Rhino.DocObjects.ObjectAttributes ();

          att.LayerIndex = toBake.LayerIndex;
          att.ObjectColor = Color.DodgerBlue;
          RhinoDocument.Objects.AddText(textentity, att);
        }

        // just for vis
        var crv = textentity.Explode();

        foreach (var item in crv)
        {
          curves.Add(item);


        }
      }
    }



    A = curves;
    B = origins;
  }

  // <Custom additional code> 
  public static double ToRadians(double degrees)
  {
    return degrees * Math.PI / 180;
  } 

@rawitscher-torres
Thanks.
It’s a nice solution, but I want the script to be dynamic, so not dependent on Rhino geometry.
I want it to be a list of texts or strings in GH and then manipulate that in GH to give me what I want.
For example, if I want to make the circle bigger or smaller etc., your script means to bake points again and so on…

Plus it’s in C# which is cool but I need an IronPython solution for this, due to the specific errors with that language here…

Thanks! :slight_smile:

Just realized I was not getting the proper center points, thats why the rotation does not look right. I updated the code above to correct that

I dont really know what your ultimate goal is, but I think you can build on top of the logic that @Helvetosaur and I sketched out . Your error messege is a python one. A lot of the times when I encounter strange error messeges which are language specific and I have never seen before I always google it. Most of the times you can find many people that had a similar problem, and then that helps to solve yours. A very popular forum for programming questions is called https://stackoverflow.com/ and pretty much every time you google an issue that is the first place that will appear in your search.

Hi,
Yes, I know SO and use it a lot, and I tried google too before I posted here.
I didn’t find a solution.

My ultimate goal is to generate inside GH, without Rhino geometry, a series of strings or text objects around a circle, so that they are oriented towards the center of the circle.

You don’t need Python for that, that is easily done with normal GH components I think…

Now I feel a bit silly :slight_smile:

I was focused on a python solution. Would still be cool to know if this is solvable in python.
You’re right, standard GH components work without a problem.

Thanks!