From acfa6723c95c4aecb21d1d45dcd8208126be2095 Mon Sep 17 00:00:00 2001 From: codex Date: Fri, 7 Aug 2026 09:47:20 +0300 Subject: [PATCH] feat: read p-rec-annot connector ports --- .../src/PRecAnnot.Abstractions/Contracts.cs | 14 +++++- .../PlantConnectorPortReader.cs | 46 +++++++++++++++++++ .../PlantConnectorRelationshipReader.cs | 12 ++++- 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 Plant3D2026/P_Rec_Annot/src/PRecAnnot.Plant3D2026/PlantConnectorPortReader.cs diff --git a/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Abstractions/Contracts.cs b/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Abstractions/Contracts.cs index a5cfabd..84c508e 100644 --- a/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Abstractions/Contracts.cs +++ b/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Abstractions/Contracts.cs @@ -104,12 +104,24 @@ public sealed record PlantConnectorRelationshipSnapshot( long SecondPartRowId, long FirstLineGroupRowId, long SecondLineGroupRowId, - IReadOnlyList Diagnostics); + IReadOnlyList Diagnostics, + string? ConnectorEntityStableId = null); public sealed record PlantConnectorRelationshipReadResult(bool Success, IReadOnlyList Connectors, string? FailureCode = null); public interface IPlantConnectorRelationshipReader { PlantConnectorRelationshipReadResult Read(); } +public sealed record PlantConnectorPortSnapshot( + string ConnectorStableId, + Point3Dto FirstPosition, + Point3Dto SecondPosition, + Point3Dto FirstDirection, + Point3Dto SecondDirection); +public sealed record PlantConnectorPortReadResult(bool Success, PlantConnectorPortSnapshot? Ports, string? FailureCode = null); +public interface IPlantConnectorPortReader +{ + PlantConnectorPortReadResult Read(PlantConnectorRelationshipSnapshot connector); +} public sealed record LineNumberOwnedRow(string SourceStableId, int MarkerNumber, string Text, AnnotationPoint MarkerAttributePosition); public sealed record LineNumberRowMutation(string SourceStableId, int PreviousMarkerNumber, int MarkerNumber, string Text, AnnotationPoint? MarkerAttributePosition); public sealed record LineNumberTextAsset(string Layer, string TextStyle, double Size, string TextValue, Point2Dto Position); diff --git a/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Plant3D2026/PlantConnectorPortReader.cs b/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Plant3D2026/PlantConnectorPortReader.cs new file mode 100644 index 0000000..8be968b --- /dev/null +++ b/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Plant3D2026/PlantConnectorPortReader.cs @@ -0,0 +1,46 @@ +using Autodesk.AutoCAD.DatabaseServices; +using Autodesk.ProcessPower.PnP3dObjects; +using PRecAnnot.Abstractions; + +namespace PRecAnnot.Plant3D2026; + +// Reads the actual two Plant Connector ports from the source model database. +// Paper-space projection and viewport filtering deliberately stay in the Ortho +// adapter; this boundary only exposes stable, Autodesk-free model geometry. +internal sealed class PlantConnectorPortReader(Database sourceModelDatabase) : IPlantConnectorPortReader +{ + public PlantConnectorPortReadResult Read(PlantConnectorRelationshipSnapshot connector) + { + if (!TryObjectId(connector.ConnectorEntityStableId, out var id)) return new(false, null, "CONNECTOR_ENTITY_HANDLE_UNAVAILABLE"); + try + { + using var transaction = sourceModelDatabase.TransactionManager.StartOpenCloseTransaction(); + if (transaction.GetObject(id, OpenMode.ForRead) is not Connector entity) return new(false, null, "CONNECTOR_ENTITY_NOT_FOUND"); + var ports = entity.GetPorts(PortType.Both); + if (ports.Count != 2) return new(false, null, "CONNECTOR_PORT_COUNT_INVALID"); + var first = ports[0]; + var second = ports[1]; + return new(true, new( + connector.StableId, + Point(first.Position), + Point(second.Position), + Vector(first.Direction), + Vector(second.Direction))); + } + catch (Autodesk.AutoCAD.Runtime.Exception) { return new(false, null, "CONNECTOR_PORT_READ_FAILED"); } + catch (Exception) { return new(false, null, "CONNECTOR_PORT_READ_FAILED"); } + } + + private bool TryObjectId(string? stableId, out ObjectId id) + { + id = ObjectId.Null; + const string prefix = "acad:"; + if (string.IsNullOrWhiteSpace(stableId) || !stableId.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) || + !long.TryParse(stableId[prefix.Length..], System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out var handle)) return false; + try { id = sourceModelDatabase.GetObjectId(false, new Handle(handle), 0); return !id.IsNull; } + catch { return false; } + } + + private static Point3Dto Point(Autodesk.AutoCAD.Geometry.Point3d point) => new(point.X, point.Y, point.Z); + private static Point3Dto Vector(Autodesk.AutoCAD.Geometry.Vector3d vector) => new(vector.X, vector.Y, vector.Z); +} diff --git a/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Plant3D2026/PlantConnectorRelationshipReader.cs b/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Plant3D2026/PlantConnectorRelationshipReader.cs index 4fdfeae..73a2417 100644 --- a/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Plant3D2026/PlantConnectorRelationshipReader.cs +++ b/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Plant3D2026/PlantConnectorRelationshipReader.cs @@ -29,11 +29,21 @@ internal sealed class PlantConnectorRelationshipReader(DataLinksManager dataLink var firstGroups = dataLinks.GetRelatedRowIds("P3dLineGroupPartRelationship", "Part", firstPart, "LineGroup"); var secondGroups = dataLinks.GetRelatedRowIds("P3dLineGroupPartRelationship", "Part", secondPart, "LineGroup"); if (firstGroups.Count != 1 || secondGroups.Count != 1) continue; - result.Add(new($"pnp-connector:{connector}", connector, firstPart, secondPart, firstGroups.First(), secondGroups.First(), Array.Empty())); + result.Add(new($"pnp-connector:{connector}", connector, firstPart, secondPart, firstGroups.First(), secondGroups.First(), Array.Empty(), TryEntityStableId(row))); } return new(true, result.OrderBy(value => value.StableId, StringComparer.Ordinal).ToArray()); } catch (DLException) { return new(false, Array.Empty(), "CONNECTOR_DATALINKS_READ_FAILED"); } catch (Exception) { return new(false, Array.Empty(), "CONNECTOR_RELATIONSHIP_READ_FAILED"); } } + + private static string? TryEntityStableId(dynamic row) + { + try + { + var handle = Convert.ToInt64(row["DwgHandleLow"], System.Globalization.CultureInfo.InvariantCulture); + return handle > 0 ? $"acad:{handle:X}" : null; + } + catch { return null; } + } }