C# AutoCAD 图纸合并以及拆分
拆分和合并非常常规的需求
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using Microsoft.VisualBasic.ApplicationServices; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Application = Autodesk.AutoCAD.ApplicationServices.Application; namespace MyTestDll { public class 拆分合并图纸 { #region 拆分图纸 [CommandMethod("CF", CommandFlags.Session)] public void 按块名称拆分图纸() { Document acDoc = Application.DocumentManager.MdiActiveDocument; Database acCurDb = acDoc.Database; //选择一个图框 var acEd = acDoc.Editor; try { var peo = new PromptEntityOptions("选择一个图框块") { AllowObjectOnLockedLayer = false, AllowNone = false }; peo.SetRejectMessage("选择一个图框块"); peo.AddAllowedClass(typeof(BlockReference), true); var per = acEd.GetEntity(peo); if (per.Status != PromptStatus.OK) { Application.ShowAlertDialog("选择图框失败!"); return; } List<string> fns = new List<string>(); dynamic acadApp = Application.AcadApplication; //获取图块名称 var blkName = string.Empty; using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()) { var blkref = per.ObjectId.GetObject(OpenMode.ForRead) as BlockReference; var btr = acTrans.GetObject(blkref.IsDynamicBlock ? blkref.DynamicBlockTableRecord : blkref.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; acEd.WriteMessage(btr.Name); var oids = btr.IsAnonymous ? btr.GetAnonymousBlockIds() : btr.GetBlockReferenceIds(false, false); blkName = btr.Name; } using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()) { var bt = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable; var btrMs = acTrans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord; foreach (ObjectId item in btrMs) { var ent = item.GetObject(OpenMode.ForRead) as Entity; if (!(ent is BlockReference)) continue; var blkref = ent as BlockReference; var curBlkrefBtr = acTrans.GetObject(blkref.IsDynamicBlock ? blkref.DynamicBlockTableRecord : blkref.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; if (curBlkrefBtr.Name != blkName) continue; var ext = blkref.GeometryExtentsBestFit(); var lower = new double[3] { ext.MinPoint.X, ext.MinPoint.Y, ext.MinPoint.Z }; var upper = new double[3] { ext.MaxPoint.X, ext.MaxPoint.Y, ext.MaxPoint.Z }; acadApp.ZoomExtents(); var psr = acEd.SelectCrossingWindow(ext.MinPoint, ext.MaxPoint); acadApp.ZoomWindow(lower, upper); Application.UpdateScreen(); acEd.Regen(); string newDocPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + $"\\{Path.GetFileNameWithoutExtension(acDoc.Name)}-{(curBlkrefBtr.IsAnonymous? "Anonymous" : blkName)}"; if (!Directory.Exists(newDocPath)) Directory.CreateDirectory(newDocPath); var dwgfn = Path.Combine(newDocPath, $"{blkref.Handle}.dwg"); var oids_SaveAs = new List<ObjectId> { item }; if (psr.Status == PromptStatus.OK) { oids_SaveAs.AddRange(psr.Value.GetObjectIds()); } SaveAsFile(acCurDb, dwgfn, DwgVersion.AC1027, true, oids_SaveAs.ToArray()); fns.Add(dwgfn); } } if (fns.Count > 0) { var doc = Application.DocumentManager.MdiActiveDocument; foreach (var fn in fns) { var docOpen = Application.DocumentManager.Open(fn, false); var dl = docOpen.LockDocument(); Application.DocumentManager.MdiActiveDocument = docOpen; dynamic acadDoc = docOpen.GetAcadDocument(); acadApp.ZoomExtents(); Application.UpdateScreen(); docOpen.Editor.Regen(); acadDoc.Save(); Application.DocumentManager.MdiActiveDocument = doc; dl.Dispose(); docOpen.CloseAndDiscard(); } System.Runtime.InteropServices.Marshal.ReleaseComObject(acadApp); Application.ShowAlertDialog("拆分成功!"); } else { Application.ShowAlertDialog("拆分失败!"); } } catch (System.Exception ex) { Application.ShowAlertDialog(ex.StackTrace); } } /// <summary> /// 将部分id另存为图纸.dwg/dxf /// </summary> /// <param name="db">当前数据库</param> /// <param name="filename">另存为的图纸名称,全路径,注意dxf和dwg格式均支持</param> /// <param name="IsDwgFormat">默认是dwg格式,如果是dxf格式请传入false</param> /// <param name="oids">需要导出的图元的id</param> private void SaveAsFile(Database db, string filename, DwgVersion ver = DwgVersion.AC1021, bool IsDwgFormat = true, params ObjectId[] oids) { var oidcols = new ObjectIdCollection(); oids.ToList().ForEach(oid => oidcols.Add(oid)); using (var newdb = new Database(true, false)) { db.Wblock(newdb, oidcols, Point3d.Origin, DuplicateRecordCloning.Replace); var vtrOid = newdb.CurrentViewportTableRecordId; var pros = typeof(Database).GetProperties() .Where(c => c.CanRead && c.CanWrite && (c.PropertyType == typeof(double) || c.PropertyType == typeof(bool) || c.PropertyType == typeof(int) || c.PropertyType == typeof(string))); foreach (var pi in pros) { try { pi.SetValue(newdb, pi.GetValue(db)); } catch (System.Exception) { continue; } } if (IsDwgFormat) { newdb.SaveAs(Path.ChangeExtension(filename, ".dwg"), ver); } else { newdb.DxfOut(Path.ChangeExtension(filename, ".dxf"), 16, ver); } } } #endregion #region 合并图纸 [CommandMethod("hbtz")] public void 合并图纸() { Document acDoc = Application.DocumentManager.MdiActiveDocument; Database db = acDoc.Database; Editor ed = acDoc.Editor; try { if (db.Filename != db.OriginalFileName) { Application.ShowAlertDialog("请新建一张图再使用本命令!"); return; } if (Application.GetSystemVariable("DBMOD").ToString() != "0") { Application.ShowAlertDialog("请新建一张图再使用本命令!"); return; } System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog() { Title = "选择需要合并的图纸", Multiselect = true, Filter = "dwg files (*.dwg)|*.dwg" }; if (ofd.ShowDialog() != DialogResult.OK) { Application.ShowAlertDialog("打开图纸失败!"); return; } using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; //BlockTableRecord ms = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord; Point3d pnt_Base = Point3d.Origin; var insPtDistance2OriPoint = 0.0; for (int i = 0; i < ofd.FileNames.Length; i++) { var item = ofd.FileNames[i]; if (Path.GetFileNameWithoutExtension(item).EndsWith(" ")) { Application.ShowAlertDialog($"文件名称末尾不可以包含空格\"{item}\"!\n\r"); continue; } try { var oid = ImportDrawingAsBlkstoCurDoc(db, item, true); Extents3d ext = new Extents3d(); ext.AddBlockExtents(tr.GetObject(oid, OpenMode.ForRead) as BlockTableRecord); var pt1 = Polar(pnt_Base.Add(ext.MinPoint.GetAsVector().Negate()), 0.0, insPtDistance2OriPoint); var blkrefoid = InsertBlockref(bt[BlockTableRecord.ModelSpace], "0", Path.GetFileNameWithoutExtension(item), pt1, new Scale3d(1, 1, 1), 0, br => { br.ColorIndex = 0; br.ExplodeToOwnerSpace(); br.Erase(); }); insPtDistance2OriPoint += (ext.MaxPoint.X - ext.MinPoint.X) * 1.3; } catch (System.Exception) { ed.WriteMessage($"图纸 {Path.GetFileNameWithoutExtension(item)} 插入失败,请检查原始文件\n\r"); continue; } } tr.Commit(); } ed.Regen(); dynamic acdApp = Application.AcadApplication; acdApp.ZoomExtents(); } catch (System.Exception ex) { ed.WriteMessage(ex.StackTrace); } } /// <summary> /// 计算指定距离和角度的点 /// </summary> /// <remarks>本函数仅适用于x-y平面</remarks> /// <param name="pt">基点</param> /// <param name="ang">角度,x轴正向逆时针弧度</param> /// <param name="len">距离</param> /// <returns>目标点</returns> public static Point3d Polar(Point3d pt, double ang, double len) { return pt + Vector3d.XAxis.RotateBy(ang, Vector3d.ZAxis) * len; } /// <summary> /// 将图纸作为一个块整个插入导数据库 /// </summary> /// <param name="curDb"></param> /// <param name="FileName">图纸的完整路径,dxf或者dwg都可以</param> /// <returns></returns> /// public static ObjectId ImportDrawingAsBlkstoCurDoc(Database curDb, string strFileName, bool reimport = false) { ObjectId btrid = ObjectId.Null; var BlkName = Path.GetFileNameWithoutExtension(strFileName); var fileext = Path.GetExtension(strFileName).ToLower(); using (Transaction trans = curDb.TransactionManager.StartTransaction()) { BlockTable bt = trans.GetObject(curDb.BlockTableId, OpenMode.ForRead) as BlockTable; //if(!bt.Has(BlkName)) //{ if (File.Exists(strFileName)) { using (Database dwgdb = new Database(false, true)) { switch (fileext) { case ".dwg": dwgdb.ReadDwgFile(strFileName, System.IO.FileShare.Read, true, null); break; case ".dxf": dwgdb.DxfIn(strFileName, null); break; default: break; } dwgdb.CloseInput(true); btrid = curDb.Insert(BlkName, dwgdb, reimport); dwgdb.Dispose(); //SWH_CMD.Tools.GetEditor(db).Command("_.Attsync", "Name", BlkName); } } trans.Commit(); //} //else return bt[BlkName]; } return btrid; } /// <summary> /// 插入块到图纸中 /// </summary> /// <param name="spacdId">空间id</param> /// <param name="layer">图层</param> /// <param name="blkName">块名称</param> /// <param name="position">插入点</param> /// <param name="scale">比例</param> /// <param name="blkroAngle">旋转角度,弧度制</param> /// <returns></returns> private static ObjectId InsertBlockref(ObjectId spacdId, string layer, string blkName, Point3d position, Scale3d scale, double blkroAngle, Action<BlockReference> act = null) { ObjectId blkrefID; var db = spacdId.Database; var bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable; if (!bt.Has(blkName)) return ObjectId.Null; BlockTableRecord space = spacdId.GetObject(OpenMode.ForWrite) as BlockTableRecord; blkrefID = bt[blkName]; BlockTableRecord record = blkrefID.GetObject(OpenMode.ForRead) as BlockTableRecord; BlockReference br = new BlockReference(position, blkrefID); br.ScaleFactors = scale; br.Rotation = 0; space.AppendEntity(br); br.Layer = layer; //br.Color = Color.FromColorIndex(ColorMethod.ByAci, 0); if (record.HasAttributeDefinitions) { foreach (ObjectId id in record) { var attdef = id.GetObject(OpenMode.ForRead) as AttributeDefinition; if (attdef != null) { AttributeReference ar = new AttributeReference(); ar.SetAttributeFromBlock(attdef, br.BlockTransform); ar.Position = attdef.Position.TransformBy(br.BlockTransform); ar.Rotation = attdef.Rotation; ar.AdjustAlignment(db); ar.Layer = layer; br.AttributeCollection.AppendAttribute(ar); db.TransactionManager.AddNewlyCreatedDBObject(ar, true); } } } if (act != null) act.Invoke(br); db.TransactionManager.AddNewlyCreatedDBObject(br, true); Matrix3d mt = Matrix3d.Rotation(blkroAngle, Vector3d.ZAxis, br.Position); br.TransformBy(mt); return br.ObjectId; } #endregion } public enum AcSaveAsType { ac2000_dwg = 12, //AutoCAD 2000 DWG (*.dwg) ac2000_dxf = 13, //AutoCAD 2000 DXF (*.dxf) ac2004_dwg = 24, //AutoCAD 2004 DWG (*.dwg) ac2004_dxf = 25, //AutoCAD 2004 DXF (*.dxf) ac2007_dwg = 36, //AutoCAD 2007 DWG (*.dwg) ac2007_dxf = 37, //AutoCAD 2007 DXF (*.dxf) ac2010_dwg = 48, //AutoCAD 2010 DWG (*.dwg) ac2010_dxf = 49, //AutoCAD 2010 DXF (*.dxf) ac2013_dwg = 60, //AutoCAD 2013 DWG (*.dwg) ac2013_dxf = 61, //AutoCAD 2013 DXF (*.dxf) ac2018_dwg = 64, //AutoCAD 2018 DWG (*.dwg) ac2018_dxf = 65, //AutoCAD 2018 DXF (*.dxf) } }
标签:
C# AUTOCAD NET
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~