Project Alyobabetous : Lisp Plugin for Plant 3D

In a prior post I discussed my need to dig into the Plant 3D API for the purpose of converting P3D content into Autodesk Fabrication content. Well, it was a pretty huge success and works comparably to the Revit export workflow. Check out this Sch10 stainless underground conversion example. Blue is the original P3D content and Red is my CADmep converted content.

I appropriately named this project after Zero Wing’s iconic “All your base are belong to us” phrase. Project Alyobabetous is indeed my Plant 3D converter, but that vague context is about all I’m going to share of my converter. I will however spend the rest of this post talking about the Plant 3D .Net plugin I made to extract the necessary information, provide the code to that plugin and some generic examples of how you might be able to leverage it.

I provide the following code entirely without any notion of support and it should be considered a starting point for your own projects. Your welcome to ask a question about it, but I don’t feel any obligation to dig any deeper into Plant 3D’s awkward API on your behalf than I already have. Also note that this thing works fine under specific context, but I probably have not error trapped for all types of potential P3D content or every improper way you could use the DLL and an AutoCAD Fatal Error is an entirely possible outcome by using it!

Use this link if you want the C# project code that you have to compile:
Use this link if you just want the functional DLL to use at your own risk:
Autodesk Plant 3D SDK Link:

Now that the legal and distribution aspects are over, we can actually talk about how to use these 2 lisp functions.

GetPlantValues Overview
This function will give you access to all the “string” properties and port information of a P3D Part. Which, to the best of my knowledge everything inherits from the base class Part and thus should work for all plant objects. I have noticed that Plant 3D connectors are deviants in the quantity of strings available and I wouldn’t be at all surprised if that holds true with other types of content. To combat those inconsistencies I made the output of this function a list of paired value lists. This way I could always know for sure which string property value I was looking at in my code.

GetPlantValues Syntax:
(GetPlantValues ename [string [string] . . .])

GetPlantValues: Arguments
An entity name of a plant 3D object you would like to request information from.

These are property names, but you can request ALL of them by requesting “*” and this should probably be done at first until you know exactly what you’re looking for. This function doesn’t care if you send it 10 string arguments or a single list containing 10 strings. Note that this routine is not designed to enforce a return in the order in which you provided them.

GetPlantValues: Return Values
A list containing paired lists of the PropertyName(s) & PropertyValue(s) you requested. The PORTS property is not part of the standard string properties the datalink manager provides and is a custom collection of Location & Vector points for each connector the P3D part contained. Note that the Location XYZ + Vector XYZ will give you a point exactly 1 unit distance away from that connector’s XYZ location in its native planar direction.

GetPlantValues: Examples
((“PARTSIZELONGDESC” “ELL 90 LR SCH 10S 304/304L SS A403-W 4\””) (“WEIGHT” “8.9”))

(GetPlantValues ent (list “MATCHINGPIPEOD” “LINENUMBERTAG”))

(GetPlantValues ent (list “WEIGHT” “PORTS”))
((“WEIGHT” “8.9”) (“PORTS” (“S1” ((37987.0 62838.1 6558.0) (-0.999946 0.000646985 0.0104161))) (“S2” ((37993.0 62832.1 6557.94) (-0.00064702 -1.0 6.75919e-19)))))

SetPlantValues Overview
This is my meager attempt at giving fellow lispers the ability to change something. It has been a few years since I’ve tried to actually work with plant 3D on a project, but I vividly remember the act of an Entmod fatal erroring Plant3D at the next save. This function will make an attempt at a single property value change on an entity. I say attempt because I know some of them seem to be read only; like size. I didn’t really need this for what I was doing and thus haven’t tested it extensively, but the C# code is available if you want to roll up your sleeves and make better.

SetPlantValues Syntax:
(SetPlantValues ename PropName PropValue)

SetPlantValues: Aguments
An entity name of a plant 3D object you would like to change information on.

A string representing any of the Property Names provided by the GetPlantValues function using “*” except PORTS.

A string representing the new value of you want the provided PropName to hold.

SetPlantValues: Return Values
It returns (T) if the PropName existed and made an attempt to set your provided value. It returns (nil) if the provided PropName was not found and would mean no attempts to do work were made. Note that a return of (T) does not necessarily mean the value took. You will have to do your own research to see what does and doesn’t have write access. The good news is I haven’t personally seen it crash from trying. So, it should be safe to poke and prod as much as you want.

SetPlantValues: Examples
(GetPlantValues ent “LINENUMBERTAG“)
((“LINENUMBERTAG” “D‍N‍00001”))
(SetPlantValues ent “LINENUMBERTAG” “E‍N‍10001“)
(GetPlantValues ent “LINENUMBERTAG“)
((“LINENUMBERTAG ” “EN‍10001”))

(SetPlantValues ent “HOUSEOFBIM” “E‍N‍10001“)

Used ACAD .Net References

Used P3D .Net References

Well, I certainly hope this enables somebody out there to make Plant 3D do something really cool against its will. Plant is easily the most over managed AutoCAD based piping software I’ve seen and that over management could render this utility good for nothing more than a .Net P3D project example, but at least I tried to help fellow lispers. If anyone does manage to do something cool with it please let me know about it in the comments. I’d really like to know this simple .Net implementation helped a struggling automater in some way.

10 thoughts on “Project Alyobabetous : Lisp Plugin for Plant 3D

  1. Hello! Thank you for a great plugin! is perfect read and write properties.
    Is possible to read properties of Structural Member? I try but return (nil)
    Thank you!!


    1. Officially I think the answer is ‘No’ because it wasn’t actually built out in the .Net API. However, I rarely consider anything impossible and depending on what you want to do with them, you may get some victories if you dig deep and try extreme things.


  2. Hello!
    Thank you again for your work!
    Now I use your code for auto tag numbering in P&ID and for various calculations in P3D (for example, quick calculation of the volume and weight of pipeline systems).
    While using your code I have a few questions:
    1. Can I get the properties of constructs (currently outputs (nil))?
    2. Can I change the “number” properties (I would like to change the еlevation pipe)?
    3. Can I get properties from ortho drawings? Read the article ( And I have a question: maybe in the new SDK it is possible to get the properties of the P3D object from ortho, without using PnPDwg2dUtil.dll?


    1. 1) I am not quite sure what a construct is, but it suggests its some kind of a hybrid object. Maybe the “plant” information your looking for is in a nearby object or possibly in a VLA accessible dictionary like on IsoMessages. Have you tried using (EntNext) by chance? Might have to entnext from Nil, save each of them and then even (cdr(reverse)) to back step. I don’t know, just a thought since I don’t know what those are.

      2) If you want to manipulate existing “managed parametric” content, your unlikely to be successful. This would most likely be a really large endeavor to do it correctly. My best suggestion for that would be utilizing the standard AutoCAD commands to isolate the content you want and dynamically craft crossing window points for a puppeteer to the stretch command.

      3) I have unfortunately never made/used a Plant 3D ortho’s before. I have no idea what kind of objects they produce, you’d have to send me a drawing.


    1. P&ID’s are at the heart of what we do, but our group is usually the consumers. I’ve wanted to look at P&ID for a while. I’ll poke around when I have some time. At a glance, the P&ID half of Plant looks very different than the 3D side.


    2. Looks like they were more similar than I thought with respects to how these generic setter/getter functions worked. There were no “ports” available, so I mapped the PORTS keyword to the attachment points collection for Assets and the Start/End Point for line segments. I tested the Set on the Number and Code properties, both updated the associated text. So, I guess this is working….
      Plant P&ID Version – Code
      Plant P&ID Version – 2019 DLL

      Edit: All the documentation above stands, but the the 2 lisp function names are now: “NS:PlantPNID:GenericGetValues” & “NS:PlantPNID:GenericSetValues”


  3. Nice work. The code helped in developing a custom routine to extract pipe lengths and correctly extend the cut length where there is a Field Fit weld condition.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.