Adding Underlay Hatching to MTEXT by Extracting and Offsetting Geometry

Hey @mzjensen and rest of the community. Any ideas on scripting the following process?

Inspiration is drawn from ArcGIS Pro’s “halo” labeling.

I often make exhibits for grant applications that include street names and a colored imagery underlay. I find that black text looks best with a white halo effect when placed over imagery. I’ve attached an image describing the steps I am attempting to script. I’ve been hitting a wall with trying to script it in dynamo and don’t seem to be getting anywhere. I was wondering if anyone had any ideas.

My current idea is:
1.) Copy text in place.
2.) Send “txtexp” command to civil 3d to create polylines from the text.
3.) get the boundary lines from each letter.
4.) Offset and hatch the polyline boundaries.

I ran through the process once manually to provide an example. It seems that the “txtexp” command generates lines randomly between some letters and does not immediately provide a clean outside polyline boundary, which may become an issue.

Hi @WrightEngineering ,

Have you tried anything yet in Dynamo?
If not, I would start by looking into the Civil3DToolkit package, i have used that package before for something similar like you with text.

Currently I’m turning the geometry into surfaces. I’m trying to figure out how I can combine all of the surfaces into a single surface, and then extract the perimeter curves so I can offset them. It seems like the surface combine node is just returning another list of polysurfaces when used. Ideally there would be some sort of shrinkwrap function for this step.

Hi @WrightEngineering

Could you drop here dwg file with few text objects? It will help others who is trying to help you.

1 Like

Could you just put some other white text behind it that has a slightly larger font size?

I tried to do that but can’t seem to get it to work since the background needs to be an offset of each letter. When you scale up the text size of mtext, the insertion point of each letter is no longer the same as the corresponding scaled down letters. Only way I think that would work is if every letter was its own mtext object and set to middle center alignment.

Hmmm this looks promising. Will have to try it on Monday: Polysurface Perimeter Curves (not expected result)

I’ll also post a dwg and anything else I can figure out.

So it seems that first the text has to be exploded with “txtexp” command. Then, I tried to use this linework, but the linework was returning “points are not coincident” and some portions were missing. I found if I converted the 2d polylines to 3d polylines, that fixed the issue. I’m able to use surface.byunion and surface.perimeter curves, to get the perimeter curves; however, they are not closed and I seem to be unable to close the curves with the PolyCurve.ByjoinedCurves node. When I try to join them I get “curve join produced more than one WIRE in polycurve”. I noticed the following thread fixed that issue by using a custom node; however, that node only seems available within dynamo for revit? → PolyCurve.ByjoinedCurves warning: Curve join produced more than one WIRE in PolyCurve
TextHalo.dwg (2.7 MB)

This is very similar to what I’m trying to do: Creating a 3D Letter, Curves are not closed, where is my error?

I’m realizing that the reason the code in the above forum post works, but this graph fails when trying to use the “PolyCurve.ByjoinedCurves” node, is because the curves are not grouped by letter. I need to find a way to group the curves per letter. I’m guessing finding shared start and end points may assist in this.

It seems that archi-lab has a node for this exact issue called “group_curves” that @GavinCrump references in the following post: PolyCurve.ByjoinedCurves warning: Curve join produced more than one WIRE in PolyCurve - #2 by Kulkul and is also mentioned here: Find Sets of closed curves However, I don’t believe I can access archi-lab in dynamo for civil 3d.

@Konrad_K_Sobon Is it possible to access your archi-lab package in dynamo for civil 3d? If not, could you possibly provide the code in the “group_curves” node you made so I can try to see how you accomplished this?

I’m thinking of making a new post under “geometry” as it seems a more fitting description for the current issue and reporting back here if I find anything.

Luckily someone in the following forum post has shared the code within the “group_curves” node in the following forum post: Extracting closed Polycurves from given Surface - #2 by Mohammad_Nawar

I was able to get it to work in my script, so I finally have joined polycurves that I am able to offset. However, I need a way to filter a polycurve that is contained within any polycurve that exists in a list. This is so letters like A and P only offset the exterior lines, not interior.

TextHalo.dyn (16.3 KB)

#Copyright(c) 2015, Konrad Sobon
# @arch_laboratory,

import clr
from Autodesk.DesignScript.Geometry import *

#The inputs to this node will be stored as a list in the IN variable.
dataEnteringNode = IN

inputCurves = IN[0]

#join/group curves function
def groupCurves(Line_List): 
	ignore_distance = 0.1 # Assume points this close or closer to each other are touching 
	Grouped_Lines = [] 
	Queue = set() 
	while Line_List: 
		Shape = [] 
		Queue.add(Line_List.pop()) # Move a line from the Line_List to our queue 
		while Queue: 
			Current_Line = Queue.pop() 
			for Potential_Match in Line_List: 
				Points = (Potential_Match.StartPoint, Potential_Match.EndPoint)
				for P1 in Points: 
					for P2 in (Current_Line.StartPoint, Current_Line.EndPoint): 
						distance = P1.DistanceTo(P2) 
						if distance <= ignore_distance: 
			Line_List = [item for item in Line_List if item not in Queue]
	return Grouped_Lines

OUT = groupCurves(inputCurves)

Not to discourage you, Shaun, but I have to be honest…this all seems pretty complicated. Perhaps faking a drop shadow could be a more simple alternative?


1 Like

No worries! Yeah, it ended up becoming way more complicated than I expected. I’m used to using a halo effect in arcgis and it’s only one click so I just assumed it wouldn’t be too difficult in CAD… hah. Mostly, I’ve just been trying to use it as a chance to learn more about geometry in dynamo, since I’m honestly super novice. A drop shadow is what I’ve been currently using (unscripted). I prefer the look of a halo’d text over drop shadow’d text; however, I agree it’s a much more time effective solution. I’ll be sure to steal the graph you’ve posted here for drop-shadowing until I figure out the last step to my halo script :sweat_smile: Thanks for sharing it!

I believe it is now functional. I separated out the inner curves by finding the pairs of curves that had intersecting patches and then returning the ones with the smaller area.

The finished script is attached in-case anyone wants to re-produce this effect on their text.

TextHalo.dyn (114.7 KB)