TBC Macros and Extensions

 View Only

 Help with Macro StockpileToeBoundary

Richard Rehfeldt's profile image
Richard Rehfeldt posted 01-22-2026 15:45

I'm new to creating Macros for TBC, but I've been working on one for a few days now. I finally have the UI responding somewhat as intended, but I feel like there is just something missing somewhere.

The goal of this macro create a "Toe of Slope" boundary line around a stockpile in a surface. The idea is that the user can enter a delta to represent the vertical change and that would represent the start of the side-slopes for the pile. The UI is showing dropdowns for the surface picker, but not populating with surfaces from the TBC file.

I have saved the .py and .xaml files as .txt for the upload. I am saving them as UTF-8 files.


I am all ears if anyone has any thoughts/insights. I'm still very green on this journey but would love any help!

Thank you!
Richard Rehfeldt
Senior Data Prep Tech
Emery Sapp & Sons, Inc.

Bryce Haire's profile image
Bryce Haire

Hi Richard, 
Welcome to Trimble Macros Development! Excited to have you giving it a go. 
So I took a look at your macro itself and found the following error when it tried to load the macro. 

 

If I comment out the following lines (366, 367, 371) from your python file, I see the UI load correctly. 

Some of the fun with python is the "dynamic" nature of the language where everything is "valid" and you only find out at runtime whether it works or not. 

Ronny Schneider's profile image
Ronny Schneider

Hi Richard,

kudos for coming up with such an elaborate code for your first macro. Any specific reason why you don't simply follow the example macros? I never had issues with the XAML not loading properly, and I always keep it as simple as possible. Your code for loading the UI looks overly complicate to me.

In a "StackPanel" macro that is running in the docked area I usually don't bother with "Grid" either. "Grid" is rather cumbersome to maintain if you decide to move controls around. In a floating window you must use "Grid" though.

Since Trimble is doing an outstanding job, besides no documentation in 8 years, by not keeping the sample macros available under Sample TMLs (TBC version 5.90) either, I've attached them to this message.

And still no SDK 2025.20; link for SDK 2024.10 has disappeared; latest available SDK is currently 2024.00; 

You might find something useful here as well https://github.com/RonnySchneider/SCR_Macros_Public

I always declare the NumericEdits or DistanceControls directly in the XAML, load the XAML in "def __init__" and set the base values, upper/lower bounds for them in "OnLoad", or in a "def SetDefaultOptions". You can still do sanity checks there or in "OkClicked" as you did.

And what exactly is your macro trying to achieve? Extend the triangle slope down onto another surface/elevation plane? Or simply find the outer boundary and drop it vertically down onto the other surface? There might be simpler ways to do that.

Attachment  View in library
Richard Rehfeldt's profile image
Richard Rehfeldt

Thanks for the feedback. I think I got something workable now. It is probably a little more "messy" than it needs to be, as I had a framework in place and then needed to make some adjustments. There are probably some severed connections along the way.

The goal was to take a drone surface (we use them for asphalt plant inventory) and be able to place a toe of slope around all of the piles. I am not super concerned with how closely it mimics the actual toe. I was just looking for a good visual that I could use in our drone point cloud software as a reference line.

If anyone is interested, here is the finished product. I'd be happy to hear your thoughts.

Thanks again!

Ronny Schneider's profile image
Ronny Schneider

I see.

I probably would have looked into tweaking the "explode surface" sample macro. That showcases creating line work only at a certain slope difference between neighboring triangles.

Collecting the edges and joining them, no guarantee that it is closed at that point.

from Trimble.Vce.Geometry import PolySeg, Point3D

 # use a loop to add all triangle edges that satisfy the break angle setting

bounds = List[PolySeg.PolySeg]()
b = Point3D(x,y,z)
e = Point3D(x,y,z)
p = PolySeg.PolySeg()

bounds.Add(p.Add(PolySeg.Segment.Line(b, e))) # creating a polyseg from a simple 2-point segment and add it the bounds list

# use the built-in function to join the segments as much as possible, might not be fully closed
# just throw the bounds list at it and get a shorter bounds list back
joincount = PolySeg.PolySeg.JoinTouchingPolysegs(bounds)

# draw the joined segments
wv = self.currentProject [Project.FixedSerial.WorldView]
for p in bounds:
    if isinstance(p, PolySeg.PolySeg): # this check shouldn't be necessary
        l = wv.Add(clr.GetClrType(Linestring))
        l.Append(p, None, False, False)