83 lines
5.5 KiB
C#
83 lines
5.5 KiB
C#
using Autodesk.AutoCAD.ApplicationServices;
|
|
using Autodesk.AutoCAD.DatabaseServices;
|
|
using Autodesk.AutoCAD.Geometry;
|
|
using PRecAnnot.Abstractions;
|
|
|
|
namespace PRecAnnot.Plant3D2026;
|
|
|
|
internal sealed class LineConnectionAnnotationWriter
|
|
{
|
|
private const string ApplicationName = "PXP-ALC";
|
|
|
|
public LineConnectionApplyResult Replace(Document document, string viewportStableId, IReadOnlyList<LineConnectionBoundaryPlan> plans, LineConnectionAssets assets)
|
|
{
|
|
var insertable = plans.Where(plan => plan.Reasons.Count == 0).OrderBy(plan => plan.Position.X).ThenByDescending(plan => plan.Position.Y).ToArray();
|
|
using var documentLock = document.LockDocument();
|
|
var database = document.Database;
|
|
using var transaction = database.TransactionManager.StartTransaction();
|
|
var blocks = (BlockTable)transaction.GetObject(database.BlockTableId, OpenMode.ForRead);
|
|
var layers = (LayerTable)transaction.GetObject(database.LayerTableId, OpenMode.ForRead);
|
|
var styles = (TextStyleTable)transaction.GetObject(database.TextStyleTableId, OpenMode.ForRead);
|
|
if (!blocks.Has(assets.BlockName)) throw new InvalidOperationException("LINE_CONNECTION_BLOCK_MISSING:" + assets.BlockName);
|
|
if (!layers.Has(assets.PolylineLayer)) throw new InvalidOperationException("LINE_CONNECTION_POLYLINE_LAYER_MISSING:" + assets.PolylineLayer);
|
|
if (!layers.Has(assets.TextLayer)) throw new InvalidOperationException("LINE_CONNECTION_TEXT_LAYER_MISSING:" + assets.TextLayer);
|
|
if (!styles.Has(assets.TextStyle)) throw new InvalidOperationException("LINE_CONNECTION_TEXT_STYLE_MISSING:" + assets.TextStyle);
|
|
EnsureRegApp(transaction, database);
|
|
var paper = (BlockTableRecord)transaction.GetObject(blocks[BlockTableRecord.PaperSpace], OpenMode.ForWrite);
|
|
var deleted = 0;
|
|
foreach (ObjectId id in paper)
|
|
{
|
|
var value = transaction.GetObject(id, OpenMode.ForRead);
|
|
var data = value.GetXDataForApplication(ApplicationName)?.AsArray();
|
|
if (data is null || !data.Any(item => item.TypeCode == (int)DxfCode.ExtendedDataAsciiString && string.Equals(item.Value?.ToString(), viewportStableId, StringComparison.Ordinal))) continue;
|
|
value.UpgradeOpen(); value.Erase(); deleted++;
|
|
}
|
|
var definition = (BlockTableRecord)transaction.GetObject(blocks[assets.BlockName], OpenMode.ForRead);
|
|
foreach (var plan in insertable)
|
|
{
|
|
using var reference = new BlockReference(new Point3d(plan.Position.X, plan.Position.Y, plan.Position.Z), definition.ObjectId) { LayerId = layers[assets.PolylineLayer], Rotation = plan.Rotation };
|
|
reference.XData = Ownership(viewportStableId, plan);
|
|
paper.AppendEntity(reference); transaction.AddNewlyCreatedDBObject(reference, true);
|
|
var values = new[] { plan.FirstText ?? string.Empty, plan.SecondText ?? string.Empty };
|
|
var index = 0;
|
|
foreach (ObjectId entityId in definition)
|
|
{
|
|
if (transaction.GetObject(entityId, OpenMode.ForRead) is not AttributeDefinition source || source.Constant) continue;
|
|
using var attribute = new AttributeReference();
|
|
attribute.SetAttributeFromBlock(source, reference.BlockTransform);
|
|
attribute.TextString = values[Math.Min(index++, 1)].Replace("\n", "\\P", StringComparison.Ordinal);
|
|
attribute.LayerId = layers[assets.TextLayer]; attribute.TextStyleId = styles[assets.TextStyle];
|
|
attribute.UpdateMTextAttribute(); reference.AttributeCollection.AppendAttribute(attribute); transaction.AddNewlyCreatedDBObject(attribute, true);
|
|
}
|
|
if (plan.ConnectorPosition is { } connector)
|
|
{
|
|
using var leader = new Polyline(3) { LayerId = layers[assets.PolylineLayer], XData = Ownership(viewportStableId, plan) };
|
|
leader.AddVertexAt(0, new Point2d(connector.X, connector.Y), 0, 0, 0);
|
|
// Legacy PXP-ALC uses an orthogonal two-segment leader. Its
|
|
// elbow shares the annotation Y coordinate for a stable route.
|
|
leader.AddVertexAt(1, new Point2d(connector.X, plan.Position.Y), 0, 0, 0);
|
|
leader.AddVertexAt(2, new Point2d(plan.Position.X, plan.Position.Y), 0, 0, 0);
|
|
paper.AppendEntity(leader); transaction.AddNewlyCreatedDBObject(leader, true);
|
|
}
|
|
}
|
|
transaction.Commit();
|
|
return new(deleted, insertable.Length);
|
|
}
|
|
|
|
private static ResultBuffer Ownership(string viewport, LineConnectionBoundaryPlan plan) => new(
|
|
new TypedValue((int)DxfCode.ExtendedDataRegAppName, ApplicationName),
|
|
new TypedValue((int)DxfCode.ExtendedDataAsciiString, viewport),
|
|
new TypedValue((int)DxfCode.ExtendedDataAsciiString, plan.StableId),
|
|
new TypedValue((int)DxfCode.ExtendedDataAsciiString, "LINENUMBER1"),
|
|
new TypedValue((int)DxfCode.ExtendedDataAsciiString, plan.FirstText ?? string.Empty),
|
|
new TypedValue((int)DxfCode.ExtendedDataAsciiString, "LINENUMBER2"),
|
|
new TypedValue((int)DxfCode.ExtendedDataAsciiString, plan.SecondText ?? string.Empty));
|
|
|
|
private static void EnsureRegApp(Transaction transaction, Database database)
|
|
{
|
|
var table = (RegAppTable)transaction.GetObject(database.RegAppTableId, OpenMode.ForRead);
|
|
if (table.Has(ApplicationName)) return;
|
|
table.UpgradeOpen(); using var record = new RegAppTableRecord { Name = ApplicationName }; table.Add(record); transaction.AddNewlyCreatedDBObject(record, true);
|
|
}
|
|
}
|