|
|
|
@@ -0,0 +1,111 @@
|
|
|
|
|
using Autodesk.AutoCAD.DatabaseServices;
|
|
|
|
|
using Autodesk.AutoCAD.EditorInput;
|
|
|
|
|
using Autodesk.AutoCAD.Geometry;
|
|
|
|
|
using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
|
|
|
|
|
|
|
|
|
|
namespace PRecAnnot.Plant3D2026;
|
|
|
|
|
|
|
|
|
|
// Source-backed PXP-DJ mutation boundary. The legacy command dimensions the
|
|
|
|
|
// selected PXP-OA annotation blocks, rejects mixed viewport scales and keeps
|
|
|
|
|
// all dimension creation in one transaction so native UNDO restores the prior
|
|
|
|
|
// state. The Plant-specific candidate discovery remains deliberately typed
|
|
|
|
|
// through the PXP-OA ownership contract.
|
|
|
|
|
internal static class OrthoDimensionCommand
|
|
|
|
|
{
|
|
|
|
|
private const string AnnotationApp = "PXP-OA";
|
|
|
|
|
private const string DimensionApp = "PXP-DJ";
|
|
|
|
|
|
|
|
|
|
public static void Run()
|
|
|
|
|
{
|
|
|
|
|
var document = AcadApplication.DocumentManager.MdiActiveDocument;
|
|
|
|
|
if (document is null) return;
|
|
|
|
|
var selection = document.Editor.GetSelection(new SelectionFilter(new[] { new TypedValue((int)DxfCode.ExtendedDataRegAppName, AnnotationApp) }));
|
|
|
|
|
if (selection.Status != PromptStatus.OK || selection.Value.Count < 2)
|
|
|
|
|
{
|
|
|
|
|
document.Editor.WriteMessage("\nSelect at least two PXP-OA annotations.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using var read = document.Database.TransactionManager.StartOpenCloseTransaction();
|
|
|
|
|
var points = new List<(ObjectId Id, Point3d Position, string Viewport)>();
|
|
|
|
|
foreach (var id in selection.Value.GetObjectIds())
|
|
|
|
|
{
|
|
|
|
|
if (read.GetObject(id, OpenMode.ForRead) is not BlockReference reference) continue;
|
|
|
|
|
if (!TryReadViewport(reference, out var viewport)) continue;
|
|
|
|
|
points.Add((id, reference.Position, viewport));
|
|
|
|
|
}
|
|
|
|
|
read.Commit();
|
|
|
|
|
if (points.Count < 2 || points.Select(point => point.Viewport).Distinct(StringComparer.Ordinal).Count() != 1)
|
|
|
|
|
{
|
|
|
|
|
document.Editor.WriteMessage("\nSelected annotations must belong to one Ortho viewport.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
points = points.OrderBy(point => point.Position.X).ThenBy(point => point.Position.Y).ThenBy(point => point.Id.Handle.Value).ToList();
|
|
|
|
|
var defaultAngle = Math.Abs(points[^1].Position.X - points[0].Position.X) >= Math.Abs(points[^1].Position.Y - points[0].Position.Y) ? 0d : Math.PI / 2d;
|
|
|
|
|
var angle = document.Editor.GetAngle(new PromptAngleOptions("\nDimension rotation <automatic>: ") { AllowNone = true });
|
|
|
|
|
if (angle.Status is not (PromptStatus.OK or PromptStatus.None)) return;
|
|
|
|
|
var rotation = angle.Status == PromptStatus.OK ? angle.Value : defaultAngle;
|
|
|
|
|
var offset = document.Editor.GetPoint("\nDimension line location: ");
|
|
|
|
|
if (offset.Status != PromptStatus.OK) return;
|
|
|
|
|
|
|
|
|
|
using var documentLock = document.LockDocument();
|
|
|
|
|
using var transaction = document.Database.TransactionManager.StartTransaction();
|
|
|
|
|
var table = (BlockTable)transaction.GetObject(document.Database.BlockTableId, OpenMode.ForRead);
|
|
|
|
|
var paper = (BlockTableRecord)transaction.GetObject(table[BlockTableRecord.PaperSpace], OpenMode.ForWrite);
|
|
|
|
|
EnsureRegApp(transaction, document.Database);
|
|
|
|
|
EraseOwnedDimensions(transaction, paper, points[0].Viewport, points.Select(point => point.Id.Handle.ToString()).ToHashSet(StringComparer.OrdinalIgnoreCase));
|
|
|
|
|
for (var index = 1; index < points.Count; index++)
|
|
|
|
|
{
|
|
|
|
|
var first = points[index - 1].Position;
|
|
|
|
|
var second = points[index].Position;
|
|
|
|
|
var dimension = new RotatedDimension(rotation, first, second, offset.Value, string.Empty, document.Database.Dimstyle);
|
|
|
|
|
dimension.LayerId = document.Database.Clayer;
|
|
|
|
|
dimension.XData = Ownership(points[0].Viewport, points.Select(point => point.Id.Handle.ToString()));
|
|
|
|
|
paper.AppendEntity(dimension);
|
|
|
|
|
transaction.AddNewlyCreatedDBObject(dimension, true);
|
|
|
|
|
}
|
|
|
|
|
transaction.Commit();
|
|
|
|
|
document.Editor.WriteMessage($"\nCreated {points.Count - 1} Ortho dimensions; native UNDO is available.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool TryReadViewport(BlockReference reference, out string viewport)
|
|
|
|
|
{
|
|
|
|
|
viewport = string.Empty;
|
|
|
|
|
using var data = reference.GetXDataForApplication(AnnotationApp);
|
|
|
|
|
var values = data?.AsArray().Where(value => value.TypeCode == (int)DxfCode.ExtendedDataAsciiString).Select(value => value.Value?.ToString() ?? string.Empty).ToArray();
|
|
|
|
|
if (values is null) return false;
|
|
|
|
|
for (var index = 0; index + 1 < values.Length; index++) if (string.Equals(values[index], "VIEWPORT", StringComparison.Ordinal)) { viewport = values[index + 1]; break; }
|
|
|
|
|
return !string.IsNullOrWhiteSpace(viewport);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void EraseOwnedDimensions(Transaction transaction, BlockTableRecord paper, string viewport, HashSet<string> handles)
|
|
|
|
|
{
|
|
|
|
|
foreach (ObjectId id in paper)
|
|
|
|
|
{
|
|
|
|
|
if (transaction.GetObject(id, OpenMode.ForRead) is not Entity entity) continue;
|
|
|
|
|
using var data = entity.GetXDataForApplication(DimensionApp);
|
|
|
|
|
var values = data?.AsArray().Where(value => value.TypeCode == (int)DxfCode.ExtendedDataAsciiString).Select(value => value.Value?.ToString() ?? string.Empty).ToArray();
|
|
|
|
|
if (values is null || !values.Contains(viewport, StringComparer.Ordinal)) continue;
|
|
|
|
|
if (!handles.Any(handle => values.Contains(handle, StringComparer.OrdinalIgnoreCase))) continue;
|
|
|
|
|
entity.UpgradeOpen();
|
|
|
|
|
entity.Erase();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static ResultBuffer Ownership(string viewport, IEnumerable<string> handles) => new(
|
|
|
|
|
new TypedValue((int)DxfCode.ExtendedDataRegAppName, DimensionApp),
|
|
|
|
|
new TypedValue((int)DxfCode.ExtendedDataAsciiString, viewport),
|
|
|
|
|
new TypedValue((int)DxfCode.ExtendedDataAsciiString, "SOURCES"),
|
|
|
|
|
new TypedValue((int)DxfCode.ExtendedDataAsciiString, string.Join(",", handles)));
|
|
|
|
|
|
|
|
|
|
private static void EnsureRegApp(Transaction transaction, Database database)
|
|
|
|
|
{
|
|
|
|
|
var table = (RegAppTable)transaction.GetObject(database.RegAppTableId, OpenMode.ForRead);
|
|
|
|
|
if (table.Has(DimensionApp)) return;
|
|
|
|
|
table.UpgradeOpen();
|
|
|
|
|
using var record = new RegAppTableRecord { Name = DimensionApp };
|
|
|
|
|
table.Add(record);
|
|
|
|
|
transaction.AddNewlyCreatedDBObject(record, true);
|
|
|
|
|
}
|
|
|
|
|
}
|