97 lines
5.9 KiB
C#
97 lines
5.9 KiB
C#
using Autodesk.AutoCAD.ApplicationServices;
|
|
using Autodesk.AutoCAD.DatabaseServices;
|
|
using Autodesk.AutoCAD.Geometry;
|
|
using PRecAnnot.Abstractions;
|
|
|
|
namespace PRecAnnot.Plant3D2026;
|
|
|
|
internal sealed class LineNumberOwnedAnnotationReader
|
|
{
|
|
private const string ApplicationName = "PXP-LN";
|
|
|
|
public IReadOnlyList<LineNumberOwnedRow> ReadList(Document document, ObjectId listId)
|
|
{
|
|
using var transaction = document.Database.TransactionManager.StartOpenCloseTransaction();
|
|
if (transaction.GetObject(listId, OpenMode.ForRead) is not BlockReference list || !HasRole(list, "LIST"))
|
|
throw new InvalidOperationException("LINE_NUMBER_LIST_NOT_SELECTED");
|
|
|
|
var rows = new Dictionary<int, (string? StableId, string? Text)>();
|
|
foreach (ObjectId id in list.AttributeCollection)
|
|
{
|
|
var attribute = (AttributeReference)transaction.GetObject(id, OpenMode.ForRead);
|
|
var ownership = ReadOwnership(attribute);
|
|
if (ownership is null) continue;
|
|
rows.TryGetValue(ownership.Value.MarkerNumber, out var row);
|
|
rows[ownership.Value.MarkerNumber] = ownership.Value.Role == "LINENUMBER"
|
|
? (ownership.Value.StableId, attribute.TextString.Replace("\\P", "\n", StringComparison.Ordinal))
|
|
: (ownership.Value.StableId ?? row.StableId, row.Text);
|
|
}
|
|
|
|
var result = rows.OrderBy(value => value.Key)
|
|
.Select(value => new LineNumberOwnedRow(
|
|
value.Value.StableId ?? throw new InvalidOperationException("LINE_NUMBER_ROW_STABLE_ID_MISSING"),
|
|
value.Key,
|
|
value.Value.Text ?? throw new InvalidOperationException("LINE_NUMBER_ROW_TEXT_MISSING"),
|
|
default))
|
|
.ToArray();
|
|
if (result.Length == 0) throw new InvalidOperationException("LINE_NUMBER_LIST_EMPTY");
|
|
return result;
|
|
}
|
|
|
|
public LineNumberOwnedRow ReadMarker(Document document, ObjectId markerId)
|
|
{
|
|
using var transaction = document.Database.TransactionManager.StartOpenCloseTransaction();
|
|
if (transaction.GetObject(markerId, OpenMode.ForRead) is not BlockReference marker)
|
|
throw new InvalidOperationException("LINE_NUMBER_MARKER_NOT_SELECTED");
|
|
var values = marker.GetXDataForApplication(ApplicationName)?.AsArray() ?? [];
|
|
var stableId = values.Where(value => value.TypeCode == 1000).Select(value => value.Value as string)
|
|
.FirstOrDefault(value => !string.Equals(value, "MARKER", StringComparison.OrdinalIgnoreCase));
|
|
var markerNumber = values.Where(value => value.TypeCode == 1071).Select(value => Convert.ToInt32(value.Value)).FirstOrDefault();
|
|
var text = values.Where(value => value.TypeCode == 1000).Select(value => value.Value as string).LastOrDefault() ?? string.Empty;
|
|
if (string.IsNullOrWhiteSpace(stableId) || markerNumber <= 0) throw new InvalidOperationException("LINE_NUMBER_MARKER_OWNERSHIP_MISSING");
|
|
var localPosition = Point3d.Origin;
|
|
foreach (ObjectId id in marker.AttributeCollection)
|
|
{
|
|
var attribute = (AttributeReference)transaction.GetObject(id, OpenMode.ForRead);
|
|
if (!string.Equals(attribute.Tag, "NUMBER", StringComparison.OrdinalIgnoreCase)) continue;
|
|
localPosition = attribute.Position.TransformBy(marker.BlockTransform.Inverse());
|
|
break;
|
|
}
|
|
return new(stableId, markerNumber, text, new(localPosition.X, localPosition.Y, localPosition.Z));
|
|
}
|
|
|
|
public IReadOnlyList<LineNumberOwnedRow> ReadMarkers(Document document)
|
|
{
|
|
using var transaction = document.Database.TransactionManager.StartOpenCloseTransaction();
|
|
var blocks = (BlockTable)transaction.GetObject(document.Database.BlockTableId, OpenMode.ForRead);
|
|
var paper = (BlockTableRecord)transaction.GetObject(blocks[BlockTableRecord.PaperSpace], OpenMode.ForRead);
|
|
var rows = new List<LineNumberOwnedRow>();
|
|
foreach (ObjectId id in paper)
|
|
{
|
|
if (transaction.GetObject(id, OpenMode.ForRead) is not BlockReference marker || !HasRole(marker, "MARKER")) continue;
|
|
var values = marker.GetXDataForApplication(ApplicationName)?.AsArray() ?? [];
|
|
var strings = values.Where(value => value.TypeCode == 1000).Select(value => value.Value as string).ToArray();
|
|
var stableId = strings.FirstOrDefault(value => !string.Equals(value, "MARKER", StringComparison.OrdinalIgnoreCase));
|
|
var markerNumber = values.Where(value => value.TypeCode == 1071).Select(value => Convert.ToInt32(value.Value)).FirstOrDefault();
|
|
var text = strings.LastOrDefault() ?? string.Empty;
|
|
if (string.IsNullOrWhiteSpace(stableId) || markerNumber <= 0) continue;
|
|
rows.Add(new(stableId, markerNumber, text, default));
|
|
}
|
|
return rows.OrderBy(value => value.MarkerNumber).ThenBy(value => value.SourceStableId, StringComparer.Ordinal).ToArray();
|
|
}
|
|
|
|
private static bool HasRole(BlockReference reference, string role) =>
|
|
reference.GetXDataForApplication(ApplicationName)?.AsArray().Any(value =>
|
|
value.TypeCode == 1000 && string.Equals(value.Value as string, role, StringComparison.OrdinalIgnoreCase)) == true;
|
|
|
|
private static (string? StableId, string Role, int MarkerNumber)? ReadOwnership(AttributeReference attribute)
|
|
{
|
|
var values = attribute.GetXDataForApplication(ApplicationName)?.AsArray();
|
|
if (values is null) return null;
|
|
var strings = values.Where(value => value.TypeCode == 1000).Select(value => value.Value as string).ToArray();
|
|
var role = strings.FirstOrDefault(value => value is "MARKER" or "LINENUMBER");
|
|
var number = values.Where(value => value.TypeCode == 1071).Select(value => Convert.ToInt32(value.Value)).FirstOrDefault();
|
|
return role is null || number <= 0 ? null : (strings.FirstOrDefault(value => value != role), role, number);
|
|
}
|
|
}
|