Source code for ladybug_rhino.text

"""Functions to add text to the Rhino scene and create Grasshopper text objects."""
from __future__ import division
import math

from .fromgeometry import from_plane
from .color import black

try:
    import System.Guid as guid
except ImportError as e:
    print("Failed to import System\n{}".format(e))

try:
    import Rhino as rh
except ImportError as e:
    raise ImportError("Failed to import Rhino.\n{}".format(e))

try:
    import Grasshopper as gh
except ImportError:
    pass


[docs]def text_objects(text, plane, height, font='Arial', horizontal_alignment=0, vertical_alignment=5): """Generate a Bake-able Grasshopper text object from a text string and ladybug Plane. Args: text: A text string to be converted to a a Grasshopper text object. plane: A Ladybug Plane object to locate and orient the text in the Rhino scene. height: A number for the height of the text in the Rhino scene. font: An optional text string for the font in which to draw the text. horizontal_alignment: An optional integer to specify the horizontal alignment of the text. Choose from: (0 = Left, 1 = Center, 2 = Right) vertical_alignment: An optional integer to specify the vertical alignment of the text. Choose from: (0 = Top, 1 = MiddleOfTop, 2 = BottomOfTop, 3 = Middle, 4 = MiddleOfBottom, 5 = Bottom, 6 = BottomOfBoundingBox) """ txt = rh.Display.Text3d(text, from_plane(plane), height) txt.FontFace = font txt.HorizontalAlignment = AlignmentTypes.horizontal(horizontal_alignment) txt.VerticalAlignment = AlignmentTypes.vertical(vertical_alignment) return TextGoo(txt)
"""____________EXTRA HELPER OBJECTS____________"""
[docs]class TextGoo(gh.Kernel.Types.GH_GeometricGoo[rh.Display.Text3d], gh.Kernel.IGH_BakeAwareData, gh.Kernel.IGH_PreviewData): """A Text object that can be baked and transformed in Grasshopper. The code for this entire class was taken from David Rutten and Giulio Piacentino's script described here: https://discourse.mcneel.com/t/creating-text-objects-and-outputting-them-as-normal-rhino-geometry/47834/7 Args: text: A Rhino Text3d object. """ def __init__(self, text): """Initialize Bake-able text.""" self.m_value = text
[docs] @staticmethod def DuplicateText3d(original): if original is None: return None text = rh.Display.Text3d(original.Text, original.TextPlane, original.Height) text.Bold = original.Bold text.Italic = original.Italic text.FontFace = original.FontFace return text
[docs] def DuplicateGeometry(self): return TextGoo(TextGoo.DuplicateText3d(self.m_value))
[docs] def get_TypeName(self): return "3D Text"
[docs] def get_TypeDescription(self): return "3D Text"
[docs] def get_Boundingbox(self): if self.m_value is None: return rh.Geometry.BoundingBox.Empty return self.m_value.BoundingBox
[docs] def GetBoundingBox(self, xform): if self.m_value is None: return rh.Geometry.BoundingBox.Empty box = self.m_value.BoundingBox corners = xform.TransformList(box.GetCorners()) return rh.Geometry.BoundingBox(corners)
[docs] def Transform(self, xform): text = TextGoo.DuplicateText3d(self.m_value) if text is None: return TextGoo(None) plane = text.TextPlane point = plane.PointAt(1, 1) plane.Transform(xform) point.Transform(xform) dd = point.DistanceTo(plane.Origin) text.TextPlane = plane text.Height *= dd / math.sqrt(2) new_text = TextGoo(text) new_text.m_value.Bold = self.m_value.Bold new_text.m_value.Italic = self.m_value.Italic new_text.m_value.FontFace = self.m_value.FontFace return new_text
[docs] def Morph(self, xmorph): return self.DuplicateGeometry()
[docs] def get_ClippingBox(self): return self.get_Boundingbox()
[docs] def DrawViewportWires(self, args): if self.m_value is None: return color = black() if black is not None else args.Color args.Pipeline.Draw3dText(self.m_value, color)
[docs] def DrawViewportMeshes(self, args): # Do not draw in meshing layer. pass
[docs] def BakeGeometry(self, doc, att, id): id = guid.Empty if self.m_value is None: return False, id if att is None: att = doc.CreateDefaultAttributes() original_plane = None d_txt = self.m_value.Text nl_count = len(d_txt.split('\n')) - 1 if nl_count > 1 and str(self.m_value.VerticalAlignment) == 'Bottom': y_ax = rh.Geometry.Vector3d(self.m_value.TextPlane.YAxis) txt_h = self.m_value.Height * (3 / 2) m_vec = rh.Geometry.Vector3d.Multiply(y_ax, txt_h * -nl_count) original_plane = self.m_value.TextPlane new_plane = rh.Geometry.Plane(self.m_value.TextPlane) new_plane.Translate(m_vec) self.m_value.TextPlane = new_plane self.m_value.Height = self.m_value.Height doc.ModelSpaceAnnotationScalingEnabled = False # disable model scale id = doc.Objects.AddText(self.m_value, att) self.m_value.Height = self.m_value.Height if original_plane is not None: self.m_value.TextPlane = original_plane return True, id
[docs] def ScriptVariable(self): """Overwrite Grasshopper ScriptVariable method.""" return self
[docs] def ToString(self): """Overwrite .NET ToString method.""" return self.__repr__()
def __repr__(self): if self.m_value is None: return "<null>" return self.m_value.Text
[docs]class AlignmentTypes(object): """Enumeration of text alignment types.""" _HORIZONTAL = (rh.DocObjects.TextHorizontalAlignment.Left, rh.DocObjects.TextHorizontalAlignment.Center, rh.DocObjects.TextHorizontalAlignment.Right) _VERTICAL = (rh.DocObjects.TextVerticalAlignment.Top, rh.DocObjects.TextVerticalAlignment.MiddleOfTop, rh.DocObjects.TextVerticalAlignment.BottomOfTop, rh.DocObjects.TextVerticalAlignment.Middle, rh.DocObjects.TextVerticalAlignment.MiddleOfBottom, rh.DocObjects.TextVerticalAlignment.Bottom, rh.DocObjects.TextVerticalAlignment.BottomOfBoundingBox)
[docs] @classmethod def horizontal(cls, field_number): """Get a Rhino horizontal alignment object by its integer field number. * 0 - Left * 1 - Center * 2 - Right """ return cls._HORIZONTAL[field_number]
[docs] @classmethod def vertical(cls, field_number): """Get a Rhino vertical alignment object by its integer field number. * 0 - Top * 1 - MiddleOfTop * 2 - BottomOfTop * 3 - Middle * 4 - MiddleOfBottom * 5 - Bottom * 6 - BottomOfBoundingBox """ return cls._VERTICAL[field_number]