307 lines
9.9 KiB
C#
307 lines
9.9 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text.RegularExpressions;
|
||
using Autodesk.AutoCAD.ApplicationServices;
|
||
using Autodesk.AutoCAD.DatabaseServices;
|
||
using Autodesk.AutoCAD.Runtime;
|
||
using CadParamPluging.Domain.Models;
|
||
|
||
namespace CadParamPluging.Cad
|
||
{
|
||
public static class TemplateDrawingService
|
||
{
|
||
private static readonly Regex MatchFieldRegex = new Regex(
|
||
@"^\s*(交付状态|工艺方法|结构特征|特殊条件)\s*[::]\s*(.+?)\s*$",
|
||
RegexOptions.Compiled);
|
||
|
||
private static readonly Regex MTextFormatRegex = new Regex(@"\\[A-Za-z]+[^;]*;", RegexOptions.Compiled);
|
||
|
||
public static Document CreateDocumentFromTemplate(TemplateInfo template)
|
||
{
|
||
var doc = Application.DocumentManager.Add(template.FilePath);
|
||
Application.DocumentManager.MdiActiveDocument = doc;
|
||
return doc;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除模板中用于“匹配模板/图纸”的参数标注文本(交付状态/工艺方法/结构特征/特殊条件)。
|
||
/// 仅清理当前生成图纸中目标空间(Layout 或 ModelSpace)里的文本实体/块属性。
|
||
/// </summary>
|
||
public static int RemoveMatchParameterAnnotations(CadContext ctx, string layoutName, bool scanModelSpace)
|
||
{
|
||
if (ctx == null)
|
||
{
|
||
throw new ArgumentNullException(nameof(ctx));
|
||
}
|
||
|
||
var db = ctx.Database;
|
||
var tr = ctx.Transaction;
|
||
|
||
if (scanModelSpace)
|
||
{
|
||
var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
|
||
var ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
|
||
return EraseMatchTextEntities(tr, ms);
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(layoutName))
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
var layoutDict = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
|
||
ObjectId layoutId = ObjectId.Null;
|
||
foreach (DBDictionaryEntry entry in layoutDict)
|
||
{
|
||
if (string.Equals(entry.Key, layoutName, StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
layoutId = entry.Value;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (layoutId.IsNull)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
var layout = (Layout)tr.GetObject(layoutId, OpenMode.ForRead);
|
||
var btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite);
|
||
return EraseMatchTextEntities(tr, btr);
|
||
}
|
||
|
||
private static int EraseMatchTextEntities(Transaction tr, BlockTableRecord btr)
|
||
{
|
||
if (tr == null || btr == null)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
var removed = 0;
|
||
var ids = btr.Cast<ObjectId>().ToList();
|
||
foreach (var id in ids)
|
||
{
|
||
var ent = tr.GetObject(id, OpenMode.ForWrite, false) as Entity;
|
||
if (ent == null)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if (ent is DBText t)
|
||
{
|
||
if (ContainsMatchField(t.TextString))
|
||
{
|
||
ent.Erase(true);
|
||
removed++;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if (ent is MText mt)
|
||
{
|
||
var plain = SimplifyMText(mt.Contents);
|
||
if (ContainsMatchField(plain))
|
||
{
|
||
ent.Erase(true);
|
||
removed++;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if (ent is BlockReference br)
|
||
{
|
||
foreach (ObjectId attId in br.AttributeCollection)
|
||
{
|
||
var att = tr.GetObject(attId, OpenMode.ForWrite, false) as AttributeReference;
|
||
if (att == null)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if (ContainsMatchField(att.TextString))
|
||
{
|
||
try
|
||
{
|
||
att.Erase(true);
|
||
removed++;
|
||
}
|
||
catch
|
||
{
|
||
// ignore
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return removed;
|
||
}
|
||
|
||
private static bool ContainsMatchField(string raw)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(raw))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
var lines = raw
|
||
.Replace("\r\n", "\n")
|
||
.Replace("\r", "\n")
|
||
.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)
|
||
.Select(s => (s ?? string.Empty).Trim())
|
||
.Where(s => s.Length > 0);
|
||
|
||
foreach (var line in lines)
|
||
{
|
||
if (MatchFieldRegex.IsMatch(line))
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
private static string SimplifyMText(string contents)
|
||
{
|
||
if (string.IsNullOrEmpty(contents))
|
||
{
|
||
return string.Empty;
|
||
}
|
||
|
||
var s = contents
|
||
.Replace("\\P", "\n")
|
||
.Replace("\\p", "\n")
|
||
.Replace("\\~", " ");
|
||
|
||
s = s.Replace("{", string.Empty).Replace("}", string.Empty);
|
||
s = MTextFormatRegex.Replace(s, string.Empty);
|
||
return s;
|
||
}
|
||
|
||
public static void KeepOnlyLayout(Document doc, string layoutName)
|
||
{
|
||
if (doc == null)
|
||
{
|
||
throw new ArgumentNullException(nameof(doc));
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(layoutName))
|
||
{
|
||
return;
|
||
}
|
||
|
||
using (doc.LockDocument())
|
||
{
|
||
var db = doc.Database;
|
||
var prevDb = HostApplicationServices.WorkingDatabase;
|
||
HostApplicationServices.WorkingDatabase = db;
|
||
try
|
||
{
|
||
List<string> layoutNames;
|
||
using (var tr = db.TransactionManager.StartTransaction())
|
||
{
|
||
var layoutDict = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
|
||
layoutNames = layoutDict.Cast<DBDictionaryEntry>().Select(e => e.Key).ToList();
|
||
tr.Commit();
|
||
}
|
||
|
||
if (!layoutNames.Any(n => string.Equals(n, layoutName, StringComparison.OrdinalIgnoreCase)))
|
||
{
|
||
return;
|
||
}
|
||
|
||
var lm = LayoutManager.Current;
|
||
lm.CurrentLayout = layoutName;
|
||
|
||
foreach (var name in layoutNames)
|
||
{
|
||
if (string.Equals(name, "Model", StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if (string.Equals(name, layoutName, StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
try
|
||
{
|
||
lm.DeleteLayout(name);
|
||
}
|
||
catch
|
||
{
|
||
// ignore
|
||
}
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
HostApplicationServices.WorkingDatabase = prevDb;
|
||
}
|
||
}
|
||
}
|
||
|
||
public static void KeepOnlyModelWindow(Document doc, Extents3d window)
|
||
{
|
||
if (doc == null)
|
||
{
|
||
throw new ArgumentNullException(nameof(doc));
|
||
}
|
||
|
||
using (doc.LockDocument())
|
||
{
|
||
var db = doc.Database;
|
||
using (var tr = db.TransactionManager.StartTransaction())
|
||
{
|
||
var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
|
||
var ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
|
||
|
||
var erased = 0;
|
||
var kept = 0;
|
||
|
||
foreach (ObjectId id in ms)
|
||
{
|
||
var ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;
|
||
if (ent == null)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
try
|
||
{
|
||
var ext = ent.GeometricExtents;
|
||
if (!Intersects(ext, window))
|
||
{
|
||
ent.Erase(true);
|
||
erased++;
|
||
}
|
||
else
|
||
{
|
||
kept++;
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
// 无法获取范围的对象默认保留,避免误删关键对象
|
||
kept++;
|
||
}
|
||
}
|
||
|
||
tr.Commit();
|
||
}
|
||
}
|
||
}
|
||
|
||
private static bool Intersects(Extents3d a, Extents3d b)
|
||
{
|
||
return a.MinPoint.X <= b.MaxPoint.X
|
||
&& a.MaxPoint.X >= b.MinPoint.X
|
||
&& a.MinPoint.Y <= b.MaxPoint.Y
|
||
&& a.MaxPoint.Y >= b.MinPoint.Y;
|
||
}
|
||
}
|
||
}
|