• cad.net 文字偏移及符号表


    bug:字体偏移

    动图演示:绑定参照后出现

    img

    动图演示:代码克隆后出现

    img

    img

    有问题的代码

    using Autodesk.AutoCAD.ApplicationServices;
    using Autodesk.AutoCAD.DatabaseServices;
    using Autodesk.AutoCAD.EditorInput;
    using Autodesk.AutoCAD.Runtime;
    
    namespace BlockImport
    {
        public class BlockImportClass
        {
            [CommandMethod("tt")]
            public void ImportBlocks()
            {
                DocumentCollection dm = Application.DocumentManager;
                Editor ed = dm.MdiActiveDocument.Editor;
                Database destDb = dm.MdiActiveDocument.Database;
                Database sourceDb = new Database(false, true);
                PromptResult sourceFileName;
                try
                {
                    //从命令行要求用户输入以得到要导入的块所在的源 DWG 文件的名字 
    #if false
                    sourceFileName = ed.GetString("
    输入来源DWG的完整路径: "); //把源 DWG 读入辅助数据库  
                    sourceDb.ReadDwgFile(sourceFileName.StringResult, System.IO.FileShare.Read, true, "");  
    #else
                    sourceDb.ReadDwgFile(@"D:桌面T.dwg", System.IO.FileShare.Read, true, "");
    #endif
                    //用集合变量来存储块 ID 的列表 
                    var blockIds = new ObjectIdCollection(); 
                    using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
                    {
                        //打开块表 
                        BlockTable bt = tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false) as BlockTable;
                        //在块表中检查每个块 
                        foreach (ObjectId btrId in bt)
                        { 
                            var btr = tr.GetObject(btrId, OpenMode.ForRead, false) as BlockTableRecord;
                            //只添加有名块和非 layout 块(layout 块是非 MS 和非 PS 的块)
                            if (!btr.IsAnonymous && !btr.IsLayout)
                                blockIds.Add(btrId);
                            btr.Dispose(); //释放块表记录引用变量所占用的资源 
                        }
                        bt.Dispose();//释放块表引用变量所占用的资源 //没有作改变,不需要提交事务 
                        tr.Dispose();
                    }
                    //用 WblockCloneObjects 把所有的块从源库拷贝块到目的库的块表中 
                    //这只能实现导入块到指定的数据库中,但不是深度克隆,
                    //若对块参照实行深度克隆的话,其所引用的块也会被克隆到指定的数据库中 
                    IdMapping mapping = new IdMapping();
                    sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
                    ed.WriteMessage
                        ("
    复制 "
                        + blockIds.Count.ToString()
                        + " 个块的定义"
                        //+ sourceFileName.StringResult
                        + " 到当前绘图的块表记录."
                        );
                }
                catch (Autodesk.AutoCAD.Runtime.Exception ex)
                {
                    ed.WriteMessage("
    复制过程中的错误: " + ex.Message);
                }
                sourceDb.Dispose();
            }
        }
    }
    

    这是一个kean在博客的dbx例子,也就是后台打开dwg.

    使用它时,在某些情况下单行文字/属性会出现不在文字图形的对齐点位置,此问题称为"字体偏移".

    bug图元

    单行文字或属性.

    当克隆来源使用了:"新宋体.TTF",对齐样式为:"中间,正中,中"等...非"左"的对齐方式,这将导致偏移发生.

    左: AttachmentPoint.BaseLeft

    但是由于本人测试过少,不清楚此问题的出现是否存在于所有的.TTF文件下,便已经找到了解决方案了,对此并没有详尽的bug报告.

    测试环境

    测试环境:中文版Acad2008~Acad2019

    1:使用参照面板,然后绑定

    2:使用克隆命令

    测试环境:中文版Acad2020+

    1:使用参照面板,然后绑定

    2:使用克隆命令

    3:由于这个版本桌子重写了一个新的insert命令,也就是i这个命令,它会弹出一个带预览的小面板,这个命令也会导致此问题发生.

    解决方案1:

    一旦出现了字体偏移,那么此情况会保存到dwg内.

    而当你不加载问题功能前提下,打开图纸,双击文字,它会从偏移态恢复为正常态.

    遇到此情况不妨用代码:遍历全图,移动0,0到0,0.

    解决方案2:

    1:来源数据库的文字样式表修改"新宋体"为任何一种大字体.

    2:再更改文字实体对齐方式为"左",

    3:再进行克隆(WblockCloneObjects).

    4:最后在目标数据库还原样式.(已经亲测,必须这样做,只改一项都不行)

    注意的是修改Dbtxt的对齐方式从其他时候,要提交一次事务,再开事务,才能获得到单行文字的新基点(很奇葩!),再能从新基点移动到旧基点..

    这样克隆(WblockCloneObjects)才不会出现文字矩阵的错误!!

    提供参考代码:
    一些委托函数见委托的学习

    /// <summary>
    /// 克隆来源的某个块到目标数据库
    /// 不允许事务包裹
    /// </summary>
    /// <param name="ddb">目标数据库,通常是当前数据库</param>
    /// <param name="path">来源dwg的路径</param>
    /// <param name="blockName">块名</param>    
    /// <returns></returns> 
    public static IdMapping CloneBlock(this Database ddb, string path, string blockName = null, string password = null)
    {
        if (!File.Exists(path))
        {
            return null;
        }
        IdMapping mapping = new IdMapping();//id映射                                               
        var sIds = new ObjectIdCollection(); //来源图的块id
    
        var fontsNo = new string[] { "新宋体", "宋体" };
    
        var fonstNames = new List<string>();  //st用户定义的名称
        var fonstFileNames = new List<string>();//st字体本名
    
        OpendDwg.Read(path, sdb =>
        {
            using (Transaction tr = sdb.TransactionManager.StartTransaction())//来源数据库的事务
            {
                //判断当前文件如果有新宋体,就修改为大字体 
                sdb.TraverseTextStyleTable(tr, tsRec =>
                {
                    if (fontsNo.Contains(tsRec.Font.TypeFace))//字体本名不能是这些,否则引起文字矩阵错乱导致字体偏移现象!
                    {
                        fonstNames.Add(tsRec.Name);
                        fonstFileNames.Add(tsRec.FileName);
                        tr.AddTextStyle(sdb, tsRec.Name, "txt.shx", "gbcbig.shx");
                    }
                    return false;
                });
    
                //打开块表 
                sdb.TraverseBlockTable(tr, btRec =>
                {
                    //只添加有名块和非 layout 块(layout 块是非 MS 和非 PS 的块)
                    if (!btRec.IsAnonymous && !btRec.IsLayout)
                    {
                        if (string.IsNullOrEmpty(blockName) && btRec.Name == blockName)//有输入块名的时候执行快点
                        {
                            sIds.Add(btRec.ObjectId);
                            return true;
                        }
                        else
                        {
                            sIds.Add(btRec.ObjectId);
                        }
                    }
                    btRec.Dispose(); //释放块表记录引用变量所占用的资源 
                    return false;
                });
            }
            //克隆到目标块表内
            sdb.WblockCloneObjects(sIds, ddb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
        });
        return mapping;
    }
    

    后记

    我的配置是32位修改的Acad2008安装到64位的win10上,但是我的Acad2019也会出现同样的情况,而e大用英文的2019却没有复现成功,

    所以我没能正确告诉桌子如何修改的bug(毕竟他们是歪果仁),

    后来群里有人说,如果使用了开图复制,那么文字矩阵不会出错.

    Acad2008字体偏移在外部参照绑定的时候也会出现,但是insert却不会,

    而Acad2020里面的insert小面板也会,

    可见桌子的代码传承有问题,(这个时候没有说我为什么喜欢用旧版本了吧)

    bug:Acad2008符号表NetAPI

    Acad2008.NetAPI 如果你建一个块,再删除它,再添加一个同名块,用名称获取块定义会得到删除了的那个,然后爆了,

    这在2008所有符号表上均存在,所以要循环获取并容错处理,或检测id是否已经被删除,

    而高版本已经修复了这个问题.

    (完)

  • 相关阅读:
    bugku 求getshell
    HTTP之content-type
    web之robots.txt
    HTTP之User-Agent大全
    bugku 细心
    PHP输入流
    bugku web8
    PHP中sha1()函数和md5()函数的绕过
    bugku 各种·绕过
    【学术篇】烧水问题 打表找规律做法
  • 原文地址:https://www.cnblogs.com/JJBox/p/10226119.html
Copyright © 2020-2023  润新知