CadParamPluging/Cad/TemplateDrawingService.cs

307 lines
9.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}