### Create Pipeline Example in C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md Demonstrates a complete pipeline creation process using ObjectARX for Plant 3D 2024. This example showcases method chaining and proper API usage, including setting up the project, creating pipes, connectors, and establishing connections between them. It utilizes the PipingObjectAdder for adding objects and includes error handling. ```csharp using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.Civil.ApplicationServices; using Autodesk.Civil.DatabaseServices; using Autodesk.DesignScript.Geometry; using Autodesk.ObjectARX.Plant3D.Common; using Autodesk.ObjectARX.Plant3D.Database; using Autodesk.ObjectARX.Plant3D.Spec; using Autodesk.Revit.DB; using System.Collections.Specialized; using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application; using PlantApp = Autodesk.ObjectARX.Plant3D.Application; [CommandMethod("CreatePipelineExample")] public static void CreatePipelineExample() { Database db = AcadApp.DocumentManager.MdiActiveDocument.Database; Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor; try { // Setup Project currentProject = PlantApp.CurrentProject.ProjectParts["Piping"]; DataLinksManager dlm = currentProject.DataLinksManager; DataLinksManager3d dlm3d = DataLinksManager3d.Get3dManager(dlm); ContentManager cm = ContentManager.GetContentManager(); using (Transaction tr = db.TransactionManager.StartTransaction()) { using (PipingObjectAdder adder = new PipingObjectAdder(dlm3d, db)) { // Create filters StringCollection names = new StringCollection(); StringCollection values = new StringCollection(); names.Add("NominalDiameter"); values.Add("6"); // 1. Create pipe SpecPart pipePart = FetchSpecPart("Pipe", names, values); Pipe pipe = new Pipe(); pipe.StartPoint = Point3d.Origin; pipe.EndPoint = new Point3d(100, 0, 0); pipe.OuterDiameter = (double)pipePart.PropValue("MatchingPipeOd"); adder.Add(pipePart, pipe); ObjectId pipeId = pipe.ObjectId; tr.AddNewlyCreatedDBObject(pipe, true); // 2. Get next position PortCollection pipePorts = pipe.GetPorts(PortType.Static); Point3d nextPos = pipePorts[1].Position; // 3. Create weld connector PartSizePropertiesCollection connProps = FetchConnectorSpecParts(names, values, "Buttweld"); Connector weld = CreateConnector(connProps, db, cm, currentProject); weld.Position = nextPos; weld.SetOrientation(new Vector3d(1, 0, 0), new Vector3d(0, 0, 1)); adder.Add("Buttweld", connProps, weld); ObjectId weldId = weld.ObjectId; tr.AddNewlyCreatedDBObject(weld, true); // 4. Connect pipe and weld ConnectParts(pipeId, "S2", weldId, "S1", db, currentProject); ed.WriteMessage("\nPipeline created successfully!"); } tr.Commit(); } } catch (System.Exception ex) { ed.WriteMessage("\nError: " + ex.Message); } } // Placeholder methods for FetchSpecPart, FetchConnectorSpecParts, CreateConnector, and ConnectParts // These would typically be defined elsewhere in your project or provided by the API. public static SpecPart FetchSpecPart(string typeName, StringCollection names, StringCollection values) { return null; } public static PartSizePropertiesCollection FetchConnectorSpecParts(StringCollection names, StringCollection values, string connectorType) { return null; } public static Connector CreateConnector(PartSizePropertiesCollection properties, Database db, ContentManager cm, Project project) { return null; } public static void ConnectParts(ObjectId id1, string port1, ObjectId id2, string port2, Database db, Project project) { } ``` -------------------------------- ### PipeRoute Command Execution Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/docs/Extracts/GUID-5CC931A7-A16D-459D-BEA6-C138331E7B57.htm Command syntax for creating piping routes using the PipeRoute command. This example demonstrates creating two piping tubes and an elbow by specifying start coordinates, pipe specification, size, and end coordinates. ```plaintext NETLOAD PipeRouting PipeRoute 0,0,0 specification CS300 size 4" 72,0,0 72,36,0 ``` -------------------------------- ### Create Complete Pipe Assembly in C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md This workflow demonstrates the creation of a full pipe assembly. It covers initializing necessary managers, creating a pipe with specific start and end points and diameter, creating a connector, and then connecting these two parts using the Plant 3D API. ```csharp // Initialize managers Database db = AcadApp.DocumentManager.MdiActiveDocument.Database; Project currentProject = PlantApp.CurrentProject.ProjectParts["Piping"]; DataLinksManager dlm = currentProject.DataLinksManager; DataLinksManager3d dlm3d = DataLinksManager3d.Get3dManager(dlm); PipingObjectAdder pipeObjAdder = new PipingObjectAdder(dlm3d, db); using (Transaction tr = db.TransactionManager.StartTransaction()) { // 1. Create pipe SpecPart pipePart = FetchSpecPart("Pipe", propertyNames, propertyValues); Pipe pipe = new Pipe(); pipe.StartPoint = Point3d.Origin; pipe.EndPoint = new Point3d(60, 0, 0); pipe.OuterDiameter = (double)pipePart.PropValue("MatchingPipeOd"); pipeObjAdder.Add(pipePart, pipe); ObjectId pipeId = pipe.ObjectId; tr.AddNewlyCreatedDBObject(pipe, true); // 2. Get next position Point3d nextPos = FetchNextPartsPosition(pipeId, 1, db); // 3. Create connector PartSizePropertiesCollection connPropColl = FetchConnectorSpecParts(propertyNames, propertyValues, "Buttweld"); Connector connector = CreateConnector(connPropColl, db, cm, currentProject); connector.Position = nextPos; connector.SetOrientation(new Vector3d(1, 0, 0), new Vector3d(0, 0, 1)); pipeObjAdder.Add("Buttweld", connPropColl, connector); ObjectId connectorId = connector.ObjectId; tr.AddNewlyCreatedDBObject(connector, true); // 4. Connect parts ConnectParts(pipeId, "S2", connectorId, "S1", db, currentProject); tr.Commit(); } ``` -------------------------------- ### Disjoint Set Internal Methods (Example) Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/QuickGraph.txt Provides examples of internal methods used in a Disjoint Set implementation, including finding a set without path compression, finding a set with path compression, and compressing the path to the root. These are typically private helper methods. ```csharp private Element FindNoCompression(Element element) { // Implementation details... return default(Element); } private Element Find(Element element) { // Implementation details... return default(Element); } private static Void CompressPath(Element element, Element root) { // Implementation details... } ``` -------------------------------- ### Create Connector Chain in C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md This snippet illustrates the process of creating a connector, including fetching its specifications, initializing connector properties, adding subparts if necessary (like gaskets), and finally positioning and orienting the connector. ```csharp // 1. Fetch connector spec parts PartSizePropertiesCollection connectionPropColl = FetchConnectorSpecParts(propertyNames, propertyValues, "Buttweld"); // 2. Create connector Connector connector = new Connector(); connector.SlopeTolerance = 0.1; connector.OffsetTolerance = 0.0; // 3. Add subparts (for composite connectors) foreach (PartSizeProperties psp in connectionPropColl) { if (psp.Type.ToLower() == "gasket") { BlockSubPart blockSubPart = new BlockSubPart(); blockSubPart.SymbolId = cm.GetSymbol(psp, db); connector.AddSubPart(blockSubPart); } } // 4. Position connector connector.Position = nextPartPos; connector.SetOrientation(new Vector3d(1, 0, 0), new Vector3d(0, 0, 1)); ``` -------------------------------- ### Register Commands and Extension Applications in C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md Demonstrates how to register commands using the [CommandMethod] attribute and how to register an assembly as an extension application using [assembly: ExtensionApplication]. This is fundamental for creating AutoCAD plug-ins. ```csharp // Register command with proper attributes [CommandMethod("MyCommand")] public static void MyCommand() { // Command implementation } // Register assembly as extension application (if needed) [assembly: ExtensionApplication(typeof(MyExtensionApp))] [assembly: CommandClass(typeof(MyCommands))] ``` -------------------------------- ### VertexRecorderObserver Methods Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/QuickGraph.txt Defines the methods for VertexRecorderObserver, including Attach for observer setup and algorithm_DiscoverVertex for handling vertex discovery events. ```csharp public IDisposable Attach(IVertexTimeStamperAlgorithm`2 algorithm) private Void algorithm_DiscoverVertex(TVertex v) ``` -------------------------------- ### C# Inspecting Part Port Names in Plant 3D Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md Provides guidance on how to inspect and verify the names of ports associated with Plant 3D parts. Correct port naming is crucial for establishing connections. The example iterates through static ports and prints their names, emphasizing the need to check actual port names. ```csharp // Ports typically use names like: // "S1", "S2" - Standard ports // "P1", "P2" - Parametric ports // Always verify port names by inspecting the part PortCollection ports = part.GetPorts(PortType.Static); foreach (Port port in ports) { ed.WriteMessage("\nPort name: " + port.Name); } ``` -------------------------------- ### VertexTimeStamperObserver Methods Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/QuickGraph.txt Details the methods of VertexTimeStamperObserver, including Attach for observer setup and DiscoverVertex/FinishVertex for timestamping vertex events. ```csharp public IDisposable Attach(IVertexTimeStamperAlgorithm`2 algorithm) private Void DiscoverVertex(TVertex v) private Void FinishVertex(TVertex v) ``` -------------------------------- ### VertexPredecessorRecorderObserver Methods Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/QuickGraph.txt Outlines the methods for VertexPredecessorRecorderObserver, including Attach for observer setup, TreeEdge for edge processing, and TryGetPath for path retrieval. ```csharp public IDisposable Attach(ITreeBuilderAlgorithm`2 algorithm) private Void TreeEdge(TEdge e) public Boolean TryGetPath(TVertex vertex, IEnumerable`1& path) ``` -------------------------------- ### SystemInfo for Application and System Details Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/log4net.txt Provides static properties and methods for retrieving various system and application information, such as host name, application base directory, process start time, and assembly details. It includes configurable properties for null and unavailable text representations. ```csharp public class SystemInfo { public static Type[] EmptyTypes; private static Type declaringType; private static String s_hostName; private static String s_appFriendlyName; private static String s_nullText; private static String s_notAvailableText; private static DateTime s_processStartTimeUtc; private static String DEFAULT_NULL_TEXT; private static String DEFAULT_NOT_AVAILABLE_TEXT; public String NewLine { get; } public String ApplicationBaseDirectory { get; } public String ConfigurationFileLocation { get; } public String EntryAssemblyLocation { get; } public Int32 CurrentThreadId { get; } public String HostName { get; } public String ApplicationFriendlyName { get; } public DateTime ProcessStartTime { get; } public DateTime ProcessStartTimeUtc { get; } public String NullText { get; set; } public String NotAvailableText { get; set; } public static String AssemblyLocationInfo(Assembly myAssembly) { // Implementation details } public static String AssemblyQualifiedName(Type type) { // Implementation details } public static String AssemblyShortName(Assembly myAssembly) { // Implementation details } } ``` -------------------------------- ### VertexPredecessorPathRecorderObserver Methods Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/QuickGraph.txt Details the methods of VertexPredecessorPathRecorderObserver, including Attach for observer setup, TreeEdge for edge processing, and methods for path management like AllPaths. ```csharp public IDisposable Attach(IVertexPredecessorRecorderAlgorithm`2 algorithm) private Void TreeEdge(TEdge e) private Void FinishVertex(TVertex v) public IEnumerable`1 AllPaths() ``` -------------------------------- ### Utilize Helper Classes for Complex Operations in C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md Showcases the use of helper classes like RoutingHelper for complex geometric calculations such as alignment matrices and connecting entities. This promotes cleaner and more maintainable code. ```csharp // For alignment calculations Matrix3d mat = RoutingHelper.CalculateAttachMatrix( port1, RoutingHelper.CalculateNormal(port1, null), port2, RoutingHelper.CalculateNormal(port2, null)); entity.TransformBy(mat); // For connecting with alignment RoutingHelper.Connect(pair1, pair2, false, false, false, groupId, null, Tolerance.Global); ``` -------------------------------- ### Add Piping Objects using PipingObjectAdder in C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md Demonstrates how to add various piping objects (Pipe, PipeInlineAsset, Connector) to the database using the PipingObjectAdder utility. This method ensures proper handling of object creation within a transaction. ```csharp using (Transaction tr = db.TransactionManager.StartTransaction()) { using (PipingObjectAdder pipeObjAdder = new PipingObjectAdder(dlm3d, db)) { // Add pipe if (part.GetType() == typeof(Pipe)) { Pipe pipe = part as Pipe; pipeObjAdder.Add(specPart, pipe); } // Add inline asset (fitting, valve, etc.) else if (part.GetType() == typeof(PipeInlineAsset)) { PipeInlineAsset asset = part as PipeInlineAsset; pipeObjAdder.Add(specPart, asset); } // Add connector else if (part.GetType() == typeof(Connector)) { Connector connector = part as Connector; pipeObjAdder.Add(connectionName, connectionPropColl, connector); } ObjectId partId = part.ObjectId; tr.AddNewlyCreatedDBObject(part, true); } tr.Commit(); } ``` -------------------------------- ### Database Creation and Initialization Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnPDataObjects.txt Methods for creating new databases, initializing them from XML streams or DataSets, and setting up table rows. Includes static methods for creating empty databases with various cache and persistence options. ```C# internal Void InitializeFromXmlStream(String name, Stream stream) internal Void InitializeFromDataSet(String name, DataSet dset) internal Void SetTableRowsAdded(String tabname) internal static PnPDatabase CreateEmptyDatabase(PnPDatabaseLink dbparams, Boolean bUsingPersistentCache, Boolean bForceUsingPersistentCache, Boolean bForceDropPersistentCache, Boolean bCreateFullCache, Int32 version) ``` -------------------------------- ### Manage DataLinks Properties in C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md Shows how to retrieve and set properties associated with DataLinks using the DataLinksManager. This includes getting all properties, reading specific ones, and updating multiple properties efficiently. ```csharp // Get DataLinks manager DataLinksManager dlm = DataLinksManager.GetManager(dlmName); // Get all properties List> properties = dlm.GetAllProperties(objectId, true); // Read specific property foreach (var prop in properties) { if (prop.Key == "PropertyName") { string value = prop.Value; } } // Set properties StringCollection names = new StringCollection(); StringCollection values = new StringCollection(); names.Add("PropertyName"); values.Add("PropertyValue"); dlm.SetProperties(objectId, names, values); ``` -------------------------------- ### C# Code for Creating Equipment in Plant 3D 2024 Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/docs/Extracts/GUID-E20AF580-495E-4A3D-8174-5A7306CA2522.htm This C# code snippet utilizes the Autodesk.ProcessPower.PnP3dEquipment library to create equipment. It demonstrates loading available equipment types, prompting the user to select one, and then creating an instance of the selected equipment within the project. Dependencies include the AutoCAD Plant 3D SDK and the relevant .NET libraries. ```csharp using (EquipmentHelper eqHelper = new EquipmentHelper()) { //get a list of equpiment types (for example: VerticalVessel, Reboiler) foreach (EquipmentType eqt in eqHelper.EquipmentPackages) { cnt += 1; kwds.Add(cnt.ToString() + "." + eqt.DisplayName.Replace(" ", "")); } //specify the equipment type on the command line PromptResult res = ed.GetKeywords("\nSelect equipment type", kwds.ToArray()); if (res.Status == PromptStatus.OK) { int j = kwds.IndexOf(res.StringResult); EquipmentType eqt = eqHelper.EquipmentPackages[j]; // Scale and init for the project, and make current s_CurrentEquipmentType = eqHelper.MakeEquipmentForProject(eqt); s_CurrentDwgName = null; s_CurrentEquipmentId = ObjectId.Null; } } ``` -------------------------------- ### Convert ObjectId to PpObjectId using DataLinksManager in C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/docs/Extracts/GUID-44A7D9DD-E18B-45A9-ADF5-0C8F63ADD1DC.htm Demonstrates how to convert a standard ObjectId to a PpObjectId using the DataLinksManager. This example retrieves an entity from the user, gets its ObjectId, and converts it to a persistent PpObjectId that survives across AutoCAD sessions in a multi-drawing project environment. ```csharp Database db = Application.DocumentManager.MdiActiveDocument.Database; DataLinksManager dlm = DataLinksManager.GetManager(db); Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; ObjectId entId = ed.GetEntity("Pick a P&ID item: ").ObjectId; //PpObjectId PpObjectId pnpId = dlm.MakeAcPpObjectId(entId); ``` -------------------------------- ### Create Equipment from Templates in Plant 3D (C#) Source: https://context7.com/liam-at-cpc/objectarx_for_plant3d_2024/llms.txt This C# code snippet defines a command to create equipment in Plant 3D. It loads equipment from available packages, allows user selection, and interactively places the equipment in the 3D model. Dependencies include Autodesk.ProcessPower.PnP3dEquipment and Autodesk.ProcessPower.DataObjects. It takes user input for equipment selection and returns the created equipment entity. ```csharp using Autodesk.ProcessPower.PnP3dEquipment; using Autodesk.ProcessPower.DataObjects; using Autodesk.AutoCAD.EditorInput; [CommandMethod("CreateEquipment")] public static void CreateEquipment() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; Database db = Application.DocumentManager.MdiActiveDocument.Database; Project currentProject = PlantApplication.CurrentProject.ProjectParts["Piping"]; DataLinksManager dlm = currentProject.DataLinksManager; DataLinksManager3d dlm3d = DataLinksManager3d.Get3dManager(dlm); try { using (EquipmentHelper eqHelper = new EquipmentHelper()) { // Get available equipment packages List keywords = new List(); int cnt = 0; foreach (EquipmentType eqt in eqHelper.EquipmentPackages) { cnt++; keywords.Add(cnt.ToString() + "." + eqt.DisplayName.Replace(" ", "")); } PromptResult res = ed.GetKeywords( "\nSelect equipment type", keywords.ToArray()); if (res.Status == PromptStatus.OK) { int index = keywords.IndexOf(res.StringResult); EquipmentType selectedType = eqHelper.EquipmentPackages[index]; EquipmentType eqType = eqHelper.MakeEquipmentForProject(selectedType); // Create equipment entity PartSizeProperties equipPart; PartSizePropertiesCollection nozzleParts; Equipment equipment = eqHelper.CreateEquipmentEntity( eqType, null, 1.0, db, out equipPart, out nozzleParts); if (equipment != null) { // Interactive placement using jig EqDragPoint dragPoint = new EqDragPoint(equipment); if (ed.Drag(dragPoint).Status != PromptStatus.OK) { equipment.Dispose(); return; } EqDragAngle dragAngle = new EqDragAngle(equipment); ed.Drag(dragAngle); // Add to database using (Transaction tr = db.TransactionManager.StartTransaction()) { using (PipingObjectAdder adder = new PipingObjectAdder(dlm3d, db)) { adder.Add(equipPart, equipment, nozzleParts); tr.AddNewlyCreatedDBObject(equipment, true); } tr.Commit(); } ed.WriteMessage("\nEquipment created successfully!"); } } } } catch (System.Exception ex) { ed.WriteMessage("\nError: " + ex.Message); } } // Interactive jig for equipment placement public class EqDragPoint : EntityJig { Point3d m_CurrentPos; JigPromptPointOptions m_Opts; public EqDragPoint(Equipment eqEnt) : base(eqEnt) { m_CurrentPos = eqEnt.Position; m_Opts = new JigPromptPointOptions("\nSelect point"); m_Opts.UserInputControls = UserInputControls.Accept3dCoordinates; } protected override SamplerStatus Sampler(JigPrompts prompts) { PromptPointResult res = prompts.AcquirePoint(m_Opts); if (res.Status == PromptStatus.OK) { if (m_CurrentPos == res.Value) return SamplerStatus.NoChange; m_CurrentPos = res.Value; return SamplerStatus.OK; } return SamplerStatus.Cancel; } protected override bool Update() { ((Equipment)Entity).Position = m_CurrentPos; return true; } } ``` -------------------------------- ### Route and Connect Piping with AutoRoute C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/docs/Extracts/GUID-5CC931A7-A16D-459D-BEA6-C138331E7B57.htm Demonstrates how to use the AutoRoute class to create piping routes with multiple path selection. The code shows path validation, preview functionality, and user interaction for selecting between multiple routing solutions before appending to the drawing. ```csharp try { using (AutoRoute ar = new AutoRoute (m_LastPair, m_SnapPair, m_Spec, m_Size, m_CurrentPipe, m_ElbowParts, m_bStubin, m_bCutbackElbow, m_bBentPipe)) { if (ar.PathCount == 0) { return false; } else if (ar.PathCount == 1) { // Single path. Just accept it // ar.CurrentPath = 0; } else { // Select path with preview // PromptKeywordOptions opts = new PromptKeywordOptions(""); opts.Keywords.Add("Accept"); opts.Keywords.Add("Next"); opts.Keywords.Add("Previous"); opts.Keywords.Add("Undo"); opts.Keywords.Default = "Accept"; int idx = 0; while (true) { opts.Message = "\nConnect or preview next solution " + (idx+1).ToString() + " of " + ar.PathCount.ToString(); ar.CurrentPath = idx; ar.Preview(); PromptResult pRes = ed.GetKeywords(opts); if (pRes.Status != PromptStatus.OK || pRes.StringResult == "Undo") { bCancelled = true; break; } else if (pRes.StringResult == "Accept") { break; } else if (pRes.StringResult == "Next") { idx++; if (idx == ar.PathCount) { idx = 0; } opts.Keywords.Default = "Next"; } else if (pRes.StringResult == "Previous") { idx--; if (idx < 0 ) { idx = ar.PathCount-1; } opts.Keywords.Default = "Previous"; } } ar.EndPreview(); } if (bCancelled) { return false; } else { // Append // if (m_GroupId < 0) { m_GroupId = PnP3dTagFormat.findOrCreateNewLineGroup(m_LineNumber); } ar.Append(m_GroupId); return true; } } } catch { } ``` -------------------------------- ### Initialization and Finalization Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnPDataObjects.txt Methods for controlling the initialization and finalization of database-related operations. `BeginInit` and `EndInit` are typically used to bracket a series of operations that should be treated as a single unit, while `Dispose` methods handle resource cleanup. ```C# public Void BeginInit() public Void EndInit() protected Void Dispose(Boolean A_0) public Void Dispose() ``` -------------------------------- ### Implementing Database Transactions in Plant 3D Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md Illustrates the critical pattern for performing any database operations in Plant 3D, which requires wrapping modifications within a transaction. This ensures data integrity by allowing rollback in case of errors. It covers starting a transaction, creating/modifying entities, adding new objects, and committing changes. ```csharp Database db = AcadApp.DocumentManager.MdiActiveDocument.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { // 1. Create or modify entities Pipe pipe = new Pipe(); pipe.StartPoint = startPoint; pipe.EndPoint = endPoint; // 2. MUST call AddNewlyCreatedDBObject before commit tr.AddNewlyCreatedDBObject(pipe, true); // 3. Commit changes tr.Commit(); } // Key Points: // - Opening objects: tr.GetObject(objectId, OpenMode.ForRead) or OpenMode.ForWrite // - Always call tr.AddNewlyCreatedDBObject(entity, true) for NEW entities // - Call tr.Commit() at the end (failure to commit = no changes saved) ``` -------------------------------- ### Upgrade Guid Timestamp Helper Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnPDataObjects.txt A specific internal method for upgrading the Guid timestamp helper, taking a DataTable and a PnPTable as parameters. This is likely part of a data migration or versioning process. ```C# internal Void UpgradeGuidTimestampHelper(DataTable dtab, PnPTable tab) ``` -------------------------------- ### Find Parts by Identifier Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnP3dPartsRepository.txt Retrieves a Part object using its integer ID, GUID, or string GUID. Assumes a dependency on a Part object definition and the underlying data retrieval mechanism. ```C# public Part FindPart(Int32 partid) public Part FindPart(Guid guid) public Part FindPart(String guid) ``` -------------------------------- ### Database Engine and Connection Utilities Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnPDataObjects.txt Provides essential functions for creating and configuring database connections and engines. `CreateCacheDbEngine` instantiates a database engine for cache operations, while `MakeConnectionParameters` generates connection parameters from a file name. These are foundational for all database interactions within the project. ```csharp internal PnPDbEngine CreateCacheDbEngine() internal Dictionary`2 MakeConnectionParameters(String fname) ``` -------------------------------- ### Incidence Graph Outgoing Edge Operations Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/QuickGraph.txt This snippet focuses on operations related to outgoing edges in an incidence graph, such as checking if the set of outgoing edges is empty, getting the out-degree, retrieving all outgoing edges, and attempting to get outgoing edges. ```csharp +-- Methods: +-- public Boolean IsOutEdgesEmpty(TVertex v) +-- public Int32 OutDegree(TVertex v) +-- public IEnumerable`1 OutEdges(TVertex v) +-- public Boolean TryGetOutEdges(TVertex v, IEnumerable`1& edges) +-- public TEdge OutEdge(TVertex v, Int32 index) ``` -------------------------------- ### Assembly Configuration and Initialization Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/System.Data.SQLite.txt Internal and private static methods for initializing the SQLite interop layer and managing assembly configuration. Handles XML configuration file parsing, environment variable token replacement, and framework version detection. ```csharp internal static Void Initialize() internal static String GetSettingValue(String name, String default) internal static String GetNativeLibraryFileNameOnly() private static String GetAssemblyTargetFramework(Assembly assembly) private static String AbbreviateTargetFramework(String targetFramework) private static String ReplaceEnvironmentVariableTokens(String value) ``` -------------------------------- ### Get LineGroup Information for Selected SLINE in C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/docs/Extracts/GUID-E0456D3E-F77C-4815-B50D-5B9793A56E16.htm This C# code snippet retrieves information about a selected SLINE entity in AutoCAD Plant 3D. It uses the LineGroupManager to get the LineGroup ID, type, and count of associated LineSegments. It then iterates through each LineSegment to display its class name and initial vertex. ```csharp using Autodesk.ProcessPower.PnIDObjects; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; Database db = AcadApp.DocumentManager.MdiActiveDocument.Database; Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor; ObjectId entId = ed.GetEntity("Pick an SLINE: ").ObjectId; if (entId.IsNull) return; Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = db.TransactionManager; using (Transaction tr = tm.StartTransaction()) {    LineGroupManager mgr = new LineGroupManager();    int lgId = mgr.GroupId(entId);    string sMsg = "\nLineGroup: " + lgId.ToString() + " (" + mgr.Type(lgId).ToString() + ")";    ObjectIdCollection lineIds = mgr.LineDbIds(lgId);    sMsg += "\n LineSegments: " + lineIds.Count;    ed.WriteMessage(sMsg);    foreach (ObjectId lsId in lineIds)    {       LineSegment ls=(LineSegment)tm.GetObject(lsId, OpenMode.ForRead);       sMsg = "\n LineSegment: " + ls.ClassName + ", " + ls.Vertices[0].ToString();       ed.WriteMessage(sMsg);    } } ``` -------------------------------- ### PnPHelpers Class Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnPDataObjects.txt Provides utility methods for creating DataColumns, retrieving and setting properties, and finding files. ```APIDOC ## Class PnPHelpers ### Description A utility class offering various helper methods for common tasks within the ObjectARX environment, such as data column manipulation, property access, and file searching. ### Methods - **CreateColumn(String name, String caption, Type type, Int32 length, Boolean isNotNull)** - Creates a DataColumn with specified properties. - **GetBoolXProperty(DataColumn __unnamed000, String xpropname, Boolean def)** - Retrieves a boolean extended property from a DataColumn. - **SetBoolXProperty(DataColumn __unnamed000, String xpropname, Boolean value)** - Sets a boolean extended property on a DataColumn. - **GetXProperty(DataColumn __unnamed000, String xpropname, Object value)** - Retrieves an object extended property from a DataColumn. - **SetXProperty(DataColumn __unnamed000, String xpropname, Object value)** - Sets an object extended property on a DataColumn. - **FindAssemblyFile(String fname)** - Searches for a file within the application's assemblies. - **FindFile(String fname, String path)** - Searches for a file within a specified path. - **IsNumeric(Type type)** - Checks if a given type is numeric. - **GetGuid(Object obj)** - Retrieves a GUID from an object. ``` -------------------------------- ### PnPExpressionAction Enum Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnPDataObjects.txt Defines possible actions for PnP expressions, including Get and Set operations. ```APIDOC ## Enum PnPExpressionAction ### Description Enumerates the possible actions that can be performed on PnP expressions. ### Implements - IComparable - IFormattable - IConvertible ### Fields - **value__** (Int32) - The underlying integer value of the enum member. - **Get** (PnPExpressionAction) - Represents a 'Get' action. - **Set** (PnPExpressionAction) - Represents a 'Set' action. ``` -------------------------------- ### Windows Native Library Loading Methods Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/System.Data.SQLite.txt Implements Windows-specific native method calls for dynamic library loading and system information retrieval. Provides LoadLibrary for DLL loading and GetSystemInfo for processor architecture detection. ```csharp internal static IntPtr LoadLibrary(String fileName) internal static Void GetSystemInfo(SYSTEM_INFO& systemInfo) ``` -------------------------------- ### A* Shortest Path Algorithm - C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/QuickGraph.txt Implements the A* pathfinding algorithm using a Fibonacci queue for efficient vertex selection and a cost heuristic function. Supports vertex coloring, distance recording, and predecessor tracking. Includes event handlers for vertex initialization, discovery, examination, and edge relaxation. ```csharp class AStarShortestPathAlgorithm`2 : ShortestPathAlgorithmBase`3 { private FibonacciQueue`2 vertexQueue; private Dictionary`2 costs; private Func`2 costHeuristic; private VertexAction`1 InitializeVertex; private VertexAction`1 DiscoverVertex; private VertexAction`1 StartVertex; private VertexAction`1 ExamineVertex; private EdgeAction`2 ExamineEdge; private VertexAction`1 FinishVertex; private EdgeAction`2 EdgeNotRelaxed; public Func`2 CostHeuristic { get; } private Void OnEdgeNotRelaxed(TEdge e) { } private Void InternalExamineEdge(TEdge args) { } private Void InternalTreeEdge(TEdge args) { } private Void InternalGrayTarget(TEdge e) { } private Void InternalBlackTarget(TEdge e) { } protected Void Initialize() { } protected Void InternalCompute() { } private Void ComputeFromRoot(TVertex rootVertex) { } public Void ComputeNoInit(TVertex s) { } } ``` -------------------------------- ### VertexDistanceRecorderObserver Methods Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/QuickGraph.txt Defines the methods for VertexDistanceRecorderObserver, including Attach for observer setup and TreeEdge for processing edges during traversal. ```csharp public IDisposable Attach(ITreeBuilderAlgorithm`2 algorithm) private Void TreeEdge(TEdge edge) ``` -------------------------------- ### SQL Select Command Preparation - MS SQL Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnPDataObjects.txt Prepares MS SQL select commands for execution and manages resource disposal. Implements IDisposable for proper cleanup of database resources. ```csharp public Void Prepare() protected Void Dispose(Boolean A_0) ``` -------------------------------- ### Get Metadata Revision Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnPDataObjects.txt Retrieves the revision number of the metadata. This can be useful for tracking changes or determining if metadata needs to be re-synced. ```C# internal Int32 GetMetadataRevision(Boolean bPlds) ``` -------------------------------- ### POSIX Dynamic Library Loading Methods Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/System.Data.SQLite.txt Implements POSIX dlopen/dlclose operations for dynamic library loading on Unix-like systems. Includes uname system call for OS version detection and supports various RTLD flags for library linking modes. ```csharp private static Int32 uname(utsname_interop& name) internal static IntPtr dlopen(String fileName, Int32 mode) internal static Int32 dlclose(IntPtr module) internal static Boolean GetOsVersionInfo(utsname& utsName) ``` -------------------------------- ### SecurityContextProvider Class (C#) Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/log4net.txt Manages the default security context provider. It allows setting and getting the default provider and creating new security contexts. ```csharp class SecurityContextProvider { private static SecurityContextProvider s_defaultProvider; public SecurityContextProvider DefaultProvider { get; set; } public SecurityContext CreateSecurityContext(Object consumer) } ``` -------------------------------- ### SQLite Callbacks and Session Management Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/System.Data.SQLite.txt Documentation for SQLite callback delegates and session management functionalities. ```APIDOC ## SQLite Callbacks and Session Management This section covers SQLite callback delegates and the `SQLiteSession` class. ### Delegate: SQLiteReadValueCallback Callback for reading values from SQLite. #### Methods * **Invoke**(SQLiteConvert convert, SQLiteDataReader dataReader, SQLiteConnectionFlags flags, SQLiteReadEventArgs eventArgs, String typeName, Int32 index, Object userData, `Boolean&` complete) : `Void` * Description: Invokes the callback to read a value. * **BeginInvoke**(SQLiteConvert convert, SQLiteDataReader dataReader, SQLiteConnectionFlags flags, SQLiteReadEventArgs eventArgs, String typeName, Int32 index, Object userData, `Boolean&` complete, AsyncCallback callback, Object object) : `IAsyncResult` * Description: Begins an asynchronous invocation of the callback. * **EndInvoke**(`Boolean&` complete, IAsyncResult result) : `Void` * Description: Ends an asynchronous invocation. ### Delegate: SQLiteRollbackCallback Callback for rollback operations. #### Methods * **Invoke**(IntPtr puser) : `Void` * Description: Invokes the rollback callback. * **BeginInvoke**(IntPtr puser, AsyncCallback callback, Object object) : `IAsyncResult` * Description: Begins an asynchronous invocation of the rollback callback. * **EndInvoke**(IAsyncResult result) : `Void` * Description: Ends an asynchronous invocation. ### Class: SQLiteSession Manages SQLite session operations, including table filtering and change set creation. #### Methods * **IsEnabled**() : `Boolean` * **SetToEnabled**() : `Void` * **SetToDisabled**() : `Void` * **IsIndirect**() : `Boolean` * **SetToIndirect**() : `Void` * **SetToDirect**() : `Void` * **IsEmpty**() : `Boolean` * **AttachTable**(String name) : `Void` * **SetTableFilter**(SessionTableFilterCallback callback, Object clientData) : `Void` * **CreateChangeSet**(`Byte[]&` rawData) : `Void` * **CreateChangeSet**(Stream stream) : `Void` * **CreatePatchSet**(`Byte[]&` rawData) : `Void` * **CreatePatchSet**(Stream stream) : `Void` * **LoadDifferencesFromTable**(String fromDatabaseName, String tableName) : `Void` ### Class: SQLiteSessionHelpers Helper methods for SQLite session operations. #### Methods * **CheckRawData**(Byte[] rawData) : `Void` * Description: Checks the validity of raw data. ``` -------------------------------- ### Table Adoption and Configuration - C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnPDataObjects.txt Internal methods for adopting tables into a database context, checking column index base values, and verifying primary key status of columns. The Adopt method initializes table associations with a specific database and row data. ```csharp internal Void Adopt(PnPDatabase db, DataTable tab, DataRow row) internal Int32 ColumnIndexBase() ``` -------------------------------- ### Initialize SQLite Database Provider Services Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/System.Data.SQLite.txt Initializes the SQLite provider services through PreInitialize and InitializeDbProviderServices methods. Handles provider service instantiation and IServiceProvider integration for SQLite database connectivity. ```csharp internal static Void PreInitialize() private static Void InitializeDbProviderServices() private Object System.IServiceProvider.GetService(Type serviceType) private Object GetSQLiteProviderServicesInstance() ``` -------------------------------- ### UndirectedVertexDistanceRecorderObserver Methods Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/QuickGraph.txt Details the methods of the UndirectedVertexDistanceRecorderObserver class. It includes the Attach method for observer setup and a TreeEdge method for processing edges. ```csharp public IDisposable Attach(IUndirectedTreeBuilderAlgorithm`2 algorithm) private Void TreeEdge(Object sender, UndirectedEdgeEventArgs`2 args) ``` -------------------------------- ### SQLite Logging Initialization and Management (C#) Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/System.Data.SQLite.txt Manages the initialization and configuration of SQLite logging. It includes methods to initialize the logging system, add and remove default handlers, and control whether logging is enabled. Thread safety is managed using a `syncRoot` object. ```csharp public static Void Initialize() internal static Void Initialize(String className) private static Void DomainUnload(Object sender, EventArgs e) public static Void AddDefaultHandler() public static Void RemoveDefaultHandler() private static Void InitializeDefaultHandler() public Boolean Enabled { get; set; } ``` -------------------------------- ### BranchPartReference Structure Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnP3dPartsRepository.txt Defines a reference to a part within a branch. It contains a SpecPartReference and optional notes, with properties to get or set these values. ```csharp class BranchPartReference { private SpecPartReference m_partref private String m_notes SpecPartReference PartReference {get; set} String Notes {get; set} } ``` -------------------------------- ### Create and Transaction Management Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnPDataObjects.txt Methods for creating new files and managing cache transactions. `Create` initializes a new file, while `EndCacheTransaction` commits or aborts ongoing changes. ```C# internal Boolean Create(String filename) internal Void EndCacheTransaction(Boolean bCommit) ``` -------------------------------- ### UndirectedVertexPredecessorRecorderObserver Methods Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/QuickGraph.txt Outlines the methods for UndirectedVertexPredecessorRecorderObserver, including Attach for observer setup, TreeEdge for edge processing, and TryGetPath for retrieving predecessor paths. ```csharp public IDisposable Attach(IUndirectedTreeBuilderAlgorithm`2 algorithm) private Void TreeEdge(Object sender, UndirectedEdgeEventArgs`2 e) public Boolean TryGetPath(TVertex vertex, IEnumerable`1& path) ``` -------------------------------- ### Database Descriptor Operations Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnPDataObjects.txt Functions to get and load the database descriptor row. These methods are essential for reading and writing the database's configuration and metadata. ```C# internal DataRow GetDatabaseDescriptorRow() internal DataRow LoadDatabaseDescriptorRow() ``` -------------------------------- ### Creating Piping Components with Spec Parts Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md Details the method chaining pattern for creating piping components. This involves fetching a spec part based on defined properties, instantiating a `Pipe` entity, setting its properties (like start/end points and diameter) through chaining, and finally adding it to the Plant 3D database. ```csharp // 1. Fetch spec part with filters StringCollection propertyNames = new StringCollection(); StringCollection propertyValues = new StringCollection(); propertyNames.Add("NominalDiameter"); propertyValues.Add("6"); SpecPart specPart = FetchSpecPart("Pipe", propertyNames, propertyValues); // 2. Create entity Pipe pipe = new Pipe(); // 3. Set properties (method chaining) pipe.StartPoint = new Point3d(0, 0, 0); pipe.EndPoint = new Point3d(100, 0, 0); pipe.OuterDiameter = (double)specPart.PropValue("MatchingPipeOd"); // 4. Add to database ObjectId pipeId = AddToDatabase(specPart, pipe, db, dlm3d); ``` -------------------------------- ### Essential Namespaces for Plant 3D Development Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md Lists the essential C# namespaces required for developing AutoCAD Plant 3D add-ons. This includes namespaces for core AutoCAD functionalities, Plant 3D piping, Plant 3D PnID, and useful aliases for simplifying code. ```csharp using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.ProcessPower.PnP3dObjects; using Autodesk.ProcessPower.AcPp3dObjectsUtils; using Autodesk.ProcessPower.PlantInstance; using Autodesk.ProcessPower.ProjectManager; using Autodesk.ProcessPower.DataLinks; using Autodesk.ProcessPower.PnP3dDataLinks; using Autodesk.ProcessPower.P3dProjectParts; using Autodesk.ProcessPower.PartsRepository; using Autodesk.ProcessPower.PnP3dPipeRouting; using Autodesk.ProcessPower.PnIDObjects; using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application; using PlantApp = Autodesk.ProcessPower.PlantInstance.PlantApplication; ``` -------------------------------- ### Handle Nominal Diameter in C# Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/samples/CLAUDE.md Illustrates methods for creating, parsing from display strings, and comparing NominalDiameter objects in Plant 3D. This is essential for working with pipe sizes. ```csharp // Create nominal diameter NominalDiameter nd = new NominalDiameter("in", 6.0); // From display string NominalDiameter nd = NominalDiameter.FromDisplayString(null, sizeString); // Compare nominal diameters if (nd1.Equals(nd2)) { // Same size } ``` -------------------------------- ### Create Pipeline with Pipes and Connectors in C# Source: https://context7.com/liam-at-cpc/objectarx_for_plant3d_2024/llms.txt Programmatically creates a piping assembly including pipes, welds, and connectors using spec-driven part selection in AutoCAD Plant 3D. It utilizes the PipingObjectAdder and fetches parts based on specified properties like nominal diameter. Dependencies include AutoCAD Plant 3D SDK libraries. Input is implicitly defined by the command execution context and hardcoded parameters. ```csharp using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.ProcessPower.PnP3dObjects; using Autodesk.ProcessPower.PlantInstance; using Autodesk.ProcessPower.DataLinks; using Autodesk.ProcessPower.PartsRepository; using System.Collections.Specialized; [CommandMethod("CreatePipeline")] public static void CreatePipeline() { Database db = Application.DocumentManager.MdiActiveDocument.Database; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; try { Project currentProject = PlantApplication.CurrentProject.ProjectParts["Piping"]; DataLinksManager dlm = currentProject.DataLinksManager; DataLinksManager3d dlm3d = DataLinksManager3d.Get3dManager(dlm); ContentManager cm = ContentManager.GetContentManager(); using (Transaction tr = db.TransactionManager.StartTransaction()) { using (PipingObjectAdder adder = new PipingObjectAdder(dlm3d, db)) { // Create property filters for 6" nominal diameter StringCollection propNames = new StringCollection(); StringCollection propValues = new StringCollection(); propNames.Add("NominalDiameter"); propValues.Add("6"); // Fetch and create pipe SpecPart pipePart = FetchSpecPart("Pipe", propNames, propValues); Pipe pipe = new Pipe(); pipe.StartPoint = Point3d.Origin; pipe.EndPoint = new Point3d(60, 0, 0); pipe.OuterDiameter = (double)pipePart.PropValue("MatchingPipeOd"); adder.Add(pipePart, pipe); ObjectId pipeId = pipe.ObjectId; tr.AddNewlyCreatedDBObject(pipe, true); // Get end position of pipe for next component Point3d nextPos = FetchNextPartsPosition(pipeId, 1, db); // Create buttweld connector PartSizePropertiesCollection connProps = FetchConnectorSpecParts(propNames, propValues, "Buttweld"); Connector weld = CreateConnector(connProps, ref db, ref cm, ref currentProject); weld.Position = nextPos; weld.SetOrientation(new Vector3d(1, 0, 0), new Vector3d(0, 0, 1)); adder.Add("Buttweld", connProps, weld); ObjectId weldId = weld.ObjectId; tr.AddNewlyCreatedDBObject(weld, true); // Connect pipe to weld ConnectParts(pipeId, "S2", weldId, "S1", db, currentProject); ed.WriteMessage("\nPipeline created successfully!"); } tr.Commit(); } } catch (System.Exception ex) { ed.WriteMessage("\nError: " + ex.Message); } } // Helper: Fetch spec part with property filters public static SpecPart FetchSpecPart(string partType, StringCollection propertyNames, StringCollection propertyValues) { SpecManager specMgr = SpecManager.GetSpecManager(); string specName = "CS300"; if (specMgr.HasType(specName, partType)) { SpecPartReader reader = specMgr.SelectParts(specName, partType, propertyNames, propertyValues); while (reader.Next()) { SpecPart specPart = reader.Current; if (specPart.Type.Equals(partType)) { return specPart; } } } return null; } ``` -------------------------------- ### Valve Sub Type Information Source: https://github.com/liam-at-cpc/objectarx_for_plant3d_2024/blob/Arm1/inc-x64/PnP3dPartsRepository.txt Holds information about valve subtypes, including valve body type and alignment. Allows for setting and getting these properties. ```csharp public class ValveSubTypeInfo { private String m_strValveBodyType; private String m_strValveAlignment; public String ValveBodyType { get; set; } public String ValveAlignment { get; set; } } ```