TBC Macros and Extensions

 View Only
Expand all | Collapse all

Calling TBC Command from custom Macro

  • 1.  Calling TBC Command from custom Macro

    Posted 05-28-2020 05:09



    I've just started with Macros SDK in Trimble Business Center and I'm struggling a bit to find any learning material.

    I was wondering if it's possible to call an existing command from my python macro?
    In this case I would like to use Move Survey Point command and pass arguments to it using python code.


    I'm quite new to TBC so it probably doesn't help. I was trying to edit Survey Point coordinates using transformation matrix, but it didn't overwrite the coordinates.




  • 2.  Re: Calling TBC Command from custom Macro

    Posted 07-31-2020 11:25

    Hi Grzegorz,


    Yes, within the code of a TML, you can run/launch other TBC commands (including TMLs) and you can optionally pass parameter values to them.


    However, (as of 2018 at least) most commands (especially those that have UI like a dialog box or a Command Pane UI), don't have much (or any) support for passing parameters.


    And there is no formal documentation for how each command handles parameters.  They are mostly used when a command is ran from other code, and needs to set up the UI based on that code (like pre-populating fields).


    If you have questions about a specific command's parameters, you would need someone from the TBC dev team to investigate it.


    In general, you'll need to call the same code that the TBC command calls.


    In some (rare) cases, a command will provide a helper function for other UI to use.  Sometimes, there's helper code in the TBC API that clumps functionality together.


    You might also ask for a dev to post sample code on how to do something - like modify the Survey Point coordinates for example.


    Someone like @Gary Lantaff may be able to help with a short question like that (though with Survey Points, it might get complicated...).


    Hope that helps a little,




    Revenant Solutions | Trimble Community
    Independent TML Development - Build. Share. Grow.

  • 3.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-16-2022 16:49
    Hi Quan,

    Let's say if we want to create a utility network, I found "C:\Program Files (x86)\Trimble\Macros SDK\Trimble.Vce.UI.ConstructionCommands.dll" and under namespace : Trimble.Vce.UI.ConstructionCommands I found a class Trimble.Vce.UI.ConstructionCommands.CreateUtilityNodeCmd and under this class I found a constructor method CreateUtilityNodeCmd() which doesn't take any argument and also it cannot be reference. I'm really fraustrated with creating a Network and put some Nodes and Link into it. 

    Any Clue that where should I start?

    Thank you very much for the help.

    Morteza Kiani

  • 4.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-16-2022 22:01
      |   view attached
    Hello Morteza,
    I did investigate and create a sample macro for @PATRICK L'HEUREUX a short while ago.

    For Utility networks you need to use the class ​Trimble.Vce.Utility.
    Attached the sample macro, the import block is my standard that I keep adding to, that's why it is rather long and imports a lot of things that are unnecessary for this macro.

    the important stuff is
    from Trimble.Vce.Utility import UtilityNode, UtilityNetwork​
    from Trimble.Vce.Gem import SiteImprovementMaterialCollection
    ​not sure if there is better way to find the ​ SiteImprovementMaterialCollection as object, than this
            # find the the SiteImprovementMaterialCollection as object
            for o in self.currentProject:
                if isinstance(o, SiteImprovementMaterialCollection):
                    self.simc = o​
            selectednetwork = self.utilitynetworkslist.SelectedEntity()
            newnode = selectednetwork.Add(clr.GetClrType(UtilityNode))
            newnode.Name = "0000_TestNode"
            newnode.Point0 = Point3D(366660, 8117420,20)
            newnode.RimElevation = 22
            newnode.MaterialProperties = pitserial # set the pit type​

    Ronny Schneider


    SCR_CreateUtilityNode.zip   5 KB 1 version

  • 5.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-17-2022 16:01
    Thank you very much Ronny! I will look into it and educate myself.

    Morteza Kiani

  • 6.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-18-2022 11:53
    Edited by Morteza Kiani 11-18-2022 14:30
    Hi Ronny-I went through your script and It helped me  a lot on placing a utility node. I've noticed even after assigning the site improvement using the serial number(as you did) I still cannot set the invert elevation. Looks like there isn't any property under Trimble.Vce.Utility.UtilityNode for setting up the invert elevation.  What I did was just added the Z value to Point0 property. is that a derived property? I couldn't see that in the object browser?!

    Morteza Kiani

  • 7.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-20-2022 14:29
    Edited by Ronny Schneider 11-20-2022 23:25
    Hello Morteza,
    if you just want to know that elevation you can retrieve it with the property "FloorElevation", since that one is get/read only. For setting it you'll need to use Point0, see further down.
    public double FloorElevation { get; }​
    The Rim-Elevation is get/set and can be changed directly.
    RimElevation { get;  set; }

    There is no property manhole-height. You'll need to set the rim-elevation as an offset from either Floorelevation or Point0.Z.

    # lets assume o is a Untilitynode and the manhole should be 2 m high
    o.RimElevation = o.Point0.Z + 2.0
    o.RimElevation = o.FloorElevation + 2.0

    If you enable "inherited members" in the object browser you'll see some additional properties and methods.
    the important one in this case is
    that is a Point3D entity with X, Y, Z, that is setting position and invert location of the manhole.

    I believe you can't just set a new Z like o.Point0.Z = 1.22
    In one of my macros I first retrieve the Point3D into a variable, change the elevation there and then write the whole Point3D back.
    for o in self.objs:
         if isinstance(o, UtilityNode):
              p = o.Point0
              p.Z = 1.234
              o.Point0 = p​

    You could probably also do it this way, creating a new Point3D object on the fly.

    o.Point0 = Point3D(o.Point0.X, o.Point0.Y, o.Point0.Z + 1.234)

    Point3D is a commonly imported class from Trimble.Vce.Geometry that you need a lot anyway.

    Ronny Schneider

  • 8.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-21-2022 08:00
    I used Point0(x,y,z) which I figured from the code that you shared previously (SCR_CreateUtilityNode.zip). I don't know how would I had that figured without your script (Thank you!)

    Regarding the object viewer, your point was really helpful. I've noticed that while using the UtilityLine class. This class includes the inherited property (Name)  which doesn't show up in the default  view.

    Looks like I did a great job by sharing the screenshot of my Object Browser unknowingly ! lol


    Morteza Kiani

  • 9.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-21-2022 14:20
    Hello Morteza,
    I keep switching forth and back between show inherited and don't show since the list often gets to overwhelmingly crowded.

    Another way to find those things is to inspect the objects by running the macro and stopping it with a breakpoint. Then you can hover with the mouse over the variables/objects to see their contents. As you can see in this example the code is stopped in line 245, the object has been created by line 244, otherwise we couldn't actually inspect it. But the name has not been set yet, since line 245 hasn't been executed yet. But you can see all properties, including Point0.

    Ronny Schneider

  • 10.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-21-2022 17:58
    Wow! That's a great trick Rony! I appreciate sharing that!

    Morteza Kiani

  • 11.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-18-2022 17:01
    Edited by Morteza Kiani 11-18-2022 17:15
    One more question, What library do we use to create pipes?  Do we use (Trimble.Vce.Utility.UtilityLine )? That will really help me! Thanks

    Morteza Kiani

  • 12.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-19-2022 03:02
    That is correct: "desirednetwork".Add(UtilityLine)

    Patrick L'heureux

  • 13.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-21-2022 17:56
    Hey Patrick-I tried the syntax above to add Utility Line(Pipe here) to my "desiredNework" and unfortunately it doesn't add the Utility Line to the network.  It draws a utility line but two attributes are (Network and Utility Run) are empty. The current project includes a UtilityNetwork and a Utility Run but none of these data has been reflected(screenshot below). Even Start and Stop Nodes are not being populated correctly. I believe I'm not initializing the utility line correctly. Any clue that how it can be fixed? Thank you!

     below script defines two simple utility nodes , newnode1 and newnode2 and a simple utilityline that connects them.

    selectednetwork = self.utilitynetworkslist.SelectedEntity()

    # First Node
    newnode1 = selectednetwork.Add(clr.GetClrType(UtilityNode))
    newnode1.Name = "Node#_1"
    newnode1.Point0 = Point3D(-6085.240,5575,45)
    newnode1.RimElevation = 50
    newnode1.MaterialProperties = Inlet_Serial 

    # Second Node
    newnode2 = selectednetwork.Add(clr.GetClrType(UtilityNode))
    newnode2.Name = "Node#_2"
    newnode2.Point0 = Point3D(-6025.240,5575,45)
    newnode2.RimElevation = 50
    newnode2.MaterialProperties = Inlet_Serial 

    #Defining the UtilityLine that connects two nodes

    Morteza Kiani

  • 14.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-21-2022 19:29
    You need to stick to the topology/hierarchy of a TBC project. A Line is part of a run.
    From the F1-Help file which is a bit confusing.

    the Project-Explorer might be a bit clearer

    created by the following code

            selectednetwork = self.utilitynetworkslist.SelectedEntity()
            newnode1 = selectednetwork.Add(UtilityNode)
            newnode1.Name = "TestNode_1"
            newnode1.Point0 = Point3D(366660, 8117420,20)
            newnode1.RimElevation = 22
            newnode1.MaterialProperties = pitserial # set the pit type
            newnode2 = selectednetwork.Add(UtilityNode)
            newnode2.Name = "TestNode_2"
            newnode2.Point0 = Point3D(366700, 8117420,20)
            newnode2.RimElevation = 22
            newnode2.MaterialProperties = pitserial # set the pit type
            newrun = selectednetwork.Add(UtilityRun)
            newline = newrun.Add(UtilityLine)
            newline.StartNodeSerialNo = newnode1.SerialNumber
            newline.EndNodeSerialNo = newnode2.SerialNumber
            newline.StartElevationType = Utility.EndElevationType.Invert
            newline.StartEndType = Utility.PipeEndType.Calculated
            newline.Name = "TestLine_Pipe1"

    Ronny Schneider

  • 15.  RE: Re: Calling TBC Command from custom Macro

    Posted 11-21-2022 23:14
    Edited by Morteza Kiani 11-22-2022 01:34
    Yes, you're right. Same order/mindset as program should be followed here in the SDK too. I tried it and defined a Utility Run and then created a Utility Line with the right order as you described above and I believe it solved my issue.

    Again, Thank you very much for the help,

    Morteza Kiani