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

 

posted @ 2024-03-10 13:55  南胜NanSheng  阅读(176)  评论(0编辑  收藏  举报